Skip to content

Commit

Permalink
Merge branch 'master' into code_coverage
Browse files Browse the repository at this point in the history
  • Loading branch information
marvinhagemeister committed Apr 22, 2019
2 parents a108a82 + 3b7d356 commit cee03c6
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 12 deletions.
19 changes: 9 additions & 10 deletions src/diff/index.js
Expand Up @@ -101,11 +101,11 @@ export function diff(dom, parentDom, newVNode, oldVNode, context, isSvg, excessD
c._vnode = newVNode;

// Invoke getDerivedStateFromProps
let s = c._nextState || c.state;
if (c._nextState==null) {
c._nextState = c.state;
}
if (newType.getDerivedStateFromProps!=null) {
oldState = assign({}, c.state);
if (s===c.state) s = c._nextState = assign({}, s);
assign(s, newType.getDerivedStateFromProps(newVNode.props, s));
assign(c._nextState==c.state ? (c._nextState = assign({}, c._nextState)) : c._nextState, newType.getDerivedStateFromProps(newVNode.props, c._nextState));
}

// Invoke pre-render lifecycle methods
Expand All @@ -116,29 +116,28 @@ export function diff(dom, parentDom, newVNode, oldVNode, context, isSvg, excessD
else {
if (newType.getDerivedStateFromProps==null && force==null && c.componentWillReceiveProps!=null) {
c.componentWillReceiveProps(newVNode.props, cctx);
s = c._nextState || c.state;
}

if (!force && c.shouldComponentUpdate!=null && c.shouldComponentUpdate(newVNode.props, s, cctx)===false) {
if (!force && c.shouldComponentUpdate!=null && c.shouldComponentUpdate(newVNode.props, c._nextState, cctx)===false) {
dom = newVNode._dom;
c.props = newVNode.props;
c.state = s;
c.state = c._nextState;
c._dirty = false;
newVNode._lastDomChild = oldVNode._lastDomChild;
break outer;
}

if (c.componentWillUpdate!=null) {
c.componentWillUpdate(newVNode.props, s, cctx);
c.componentWillUpdate(newVNode.props, c._nextState, cctx);
}
}

oldProps = c.props;
if (!oldState) oldState = c.state;
oldState = c.state;

c.context = cctx;
c.props = newVNode.props;
c.state = s;
c.state = c._nextState;

if (options.render) options.render(newVNode);

Expand Down
20 changes: 18 additions & 2 deletions src/render.js
Expand Up @@ -9,14 +9,30 @@ import options from './options';
* @param {import('./index').ComponentChild} vnode The virtual node to render
* @param {import('./internal').PreactElement} parentDom The DOM element to
* render into
* @param {import('./dom').PreactElement} [replaceNode] Attempt to re-use an
* existing DOM tree rooted at `replaceNode`
*/
export function render(vnode, parentDom) {
export function render(vnode, parentDom, replaceNode) {
if (options.root) options.root(vnode, parentDom);
let oldVNode = parentDom._prevVNode;
vnode = createElement(Fragment, null, [vnode]);

let mounts = [];
diffChildren(parentDom, parentDom._prevVNode = vnode, oldVNode, EMPTY_OBJ, parentDom.ownerSVGElement!==undefined, oldVNode ? null : EMPTY_ARR.slice.call(parentDom.childNodes), mounts, vnode, EMPTY_OBJ);
diffChildren(
parentDom,
replaceNode ? vnode : (parentDom._prevVNode = vnode),
replaceNode ? undefined : oldVNode,
EMPTY_OBJ,
parentDom.ownerSVGElement !== undefined,
replaceNode
? [replaceNode]
: oldVNode
? null
: EMPTY_ARR.slice.call(parentDom.childNodes),
mounts,
vnode,
replaceNode || EMPTY_OBJ
);
commitRoot(mounts, vnode);
}

Expand Down
26 changes: 26 additions & 0 deletions test/browser/lifecycle.test.js
Expand Up @@ -901,6 +901,32 @@ describe('Lifecycle methods', () => {
});
});

describe('#componentWillMount', () => {
it('should update state when called setState in componentWillMount', () => {
let componentState;

class Foo extends Component {
constructor(props) {
super(props);
this.state = {
value: 0
};
}
componentWillMount() {
this.setState({ value: 1 });
}
render() {
componentState = this.state;
return <div />;
}
}

render(<Foo />, scratch);

expect(componentState).to.deep.equal({ value: 1 });
});
});

describe('#componentWillReceiveProps', () => {
it('should update state when called setState in componentWillReceiveProps', () => {
let componentState;
Expand Down
40 changes: 40 additions & 0 deletions test/browser/render.test.js
Expand Up @@ -966,4 +966,44 @@ describe('render()', () => {

expect(scratch.textContent).to.equal('01');
});

describe('replaceNode parameter', () => {

function appendChildToScratch(id) {
const child = document.createElement('div');
child.id = id;
scratch.appendChild(child);
}

beforeEach(() => {
['a', 'b', 'c'].forEach(id => appendChildToScratch(id));
});

it('should use replaceNode as render root and not inject into it', () => {
const childA = scratch.querySelector('#a');
render(<div id="a">contents</div>, scratch, childA);
expect(scratch.querySelector('#a')).to.equal(childA);
expect(childA.innerHTML).to.equal('contents');
});

it('should not remove siblings of replaceNode', () => {
const childA = scratch.querySelector('#a');
render(<div id="a" />, scratch, childA);
expect(scratch.innerHTML).to.equal('<div id="a"></div><div id="b"></div><div id="c"></div>');
});

it('should render multiple render roots in one parentDom', () => {
const childA = scratch.querySelector('#a');
const childB = scratch.querySelector('#b');
const childC = scratch.querySelector('#c');
const expectedA = '<div id="a">childA</div>';
const expectedB = '<div id="b">childB</div>';
const expectedC = '<div id="c">childC</div>';
render(<div id="a">childA</div>, scratch, childA);
render(<div id="b">childB</div>, scratch, childB);
render(<div id="c">childC</div>, scratch, childC);
expect(scratch.innerHTML).to.equal(`${expectedA}${expectedB}${expectedC}`);
});
});

});

0 comments on commit cee03c6

Please sign in to comment.