Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(fix) - scu without children #1888

Merged
merged 12 commits into from
Sep 5, 2019
5 changes: 4 additions & 1 deletion src/diff/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,11 @@ export function diff(parentDom, newVNode, oldVNode, context, isSvg, excessDomChi
c.state = c._nextState;
c._dirty = false;
c._vnode = newVNode;
newVNode._dom = oldDom!=null ? oldVNode._dom : null;
newVNode._dom = oldDom!=null ? oldDom!==oldVNode._dom ? oldDom : oldVNode._dom : null;
newVNode._children = oldVNode._children;
for (tmp = 0; tmp < newVNode._children.length; tmp++) {
if (newVNode._children[tmp]) newVNode._children[tmp]._parent = newVNode;
}
break outer;
}

Expand Down
193 changes: 190 additions & 3 deletions test/browser/lifecycles/shouldComponentUpdate.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { setupRerender } from 'preact/test-utils';
import { createElement, render, Component } from '../../../src/index';
import { createElement, render, Component, Fragment } from '../../../src/index';
import { setupScratch, teardown } from '../../_util/helpers';

/** @jsx createElement */
Expand Down Expand Up @@ -294,9 +294,9 @@ describe('Lifecycle methods', () => {
});

// issue #1864
it('should update dom pointers correctly', () => {
it('should update dom pointers correctly when returning an empty string', () => {
function Child({ showMe, counter }) {
return showMe ? <div>Counter: {counter}</div> : null;
return showMe ? <div>Counter: {counter}</div> : '';
}

class Parent extends Component {
Expand Down Expand Up @@ -362,5 +362,192 @@ describe('Lifecycle methods', () => {
rerender();
expect(scratch.textContent).to.equal('');
});

// issue #1864 second case
it('should update dom pointers correctly when returning a string', () => {
function Child({ showMe, counter }) {
return showMe ? <div>Counter: {counter}</div> : 'foo';
}

class Parent extends Component {
shouldComponentUpdate() {
return false;
}
render() {
return <Inner />;
}
}

let updateChild = () => null;
class Inner extends Component {
constructor(props) {
super(props);
this.state = { showMe: false };
updateChild = () => {
this.setState({ showMe: display = !display });
};
}
render() {
return <Child showMe={this.state.showMe} counter={0} />;
}
}

let display = false;
let updateApp = () => null;
class App extends Component {
constructor(props) {
super(props);
updateApp = () => this.setState({});
}
render() {
return (
<div>
<div />
<div />
<Parent />
</div>
);
}
}

render(<App />, scratch);
expect(scratch.textContent).to.equal('foo');

updateChild();
rerender();

expect(scratch.textContent).to.equal('Counter: 0');

updateApp();
rerender();

expect(scratch.textContent).to.equal('Counter: 0');

updateChild();
rerender();

expect(scratch.textContent).to.equal('foo');

updateApp();
rerender();
expect(scratch.textContent).to.equal('foo');
});

it('should correctly update nested chilreen', () => {
let hideThree, incrementThree;

class One extends Component {
shouldComponentUpdate() { return false; }
render(p) { return p.children; }
}

class Two extends Component {
constructor(props) {
super(props);
this.state = { hideMe: false };
hideThree = () => this.setState(s => ({ hideMe: !s.hideMe }));
}

shouldComponentUpdate(nextProps, nextState) { return this.state.hideMe !== nextState.hideMe; }

render(p, { hideMe }) {
return hideMe ? <Fragment /> : p.children;
}
}

class Three extends Component {
constructor(props) {
super(props);
this.state = { counter: 1 };
incrementThree = () => this.setState(s => ({ counter: s.counter + 1 }));
}

render(p, { counter }) { return <span>{counter}</span>; }
}

render(<One><Two><Three /></Two></One>, scratch);
expect(scratch.innerHTML).to.equal('<span>1</span>');

hideThree();
rerender();
expect(scratch.innerHTML).to.equal('');

hideThree();
rerender();
expect(scratch.innerHTML).to.equal('<span>1</span>');

incrementThree();
rerender();
expect(scratch.innerHTML).to.equal('<span>2</span>');
});

// issue #1864 third case
it('should update dom pointers correctly without siblings', () => {
function Child({ showMe, counter }) {
return showMe ? <div>Counter: {counter}</div> : 'foo';
}

class Parent extends Component {
shouldComponentUpdate() {
return false;
}
render() {
return <Inner />;
}
}

let updateChild = () => null;
class Inner extends Component {
constructor(props) {
super(props);
this.state = { showMe: false };
updateChild = () => {
this.setState({ showMe: display = !display });
};
}
render() {
return <Child showMe={this.state.showMe} counter={0} />;
}
}

let display = false;
let updateApp = () => null;
class App extends Component {
constructor(props) {
super(props);
updateApp = () => this.setState({});
}
render() {
return (
<div>
<Parent />
</div>
);
}
}

render(<App />, scratch);
expect(scratch.textContent).to.equal('foo');

updateChild();
rerender();

expect(scratch.textContent).to.equal('Counter: 0');

updateApp();
rerender();

expect(scratch.textContent).to.equal('Counter: 0');

updateChild();
rerender();

expect(scratch.textContent).to.equal('foo');

updateApp();
rerender();

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