Skip to content

Commit

Permalink
setState now creates new versions instead of mutating state
Browse files Browse the repository at this point in the history
  • Loading branch information
mitranim committed Jul 23, 2018
1 parent b8a117a commit ea932dd
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 5 deletions.
10 changes: 6 additions & 4 deletions src/component.js
Expand Up @@ -46,14 +46,16 @@ extend(Component.prototype, {

/**
* Update component state and schedule a re-render.
* @param {object} state A hash of state properties to update with new values
* @param {object} state A dict of state properties to be shallowly merged
* into the current state, or a function that will produce such a dict. The
* function is called with the current state and props.
* @param {() => void} callback A function to be called once component state is
* updated
*/
setState(state, callback) {
let s = this.state;
if (!this.prevState) this.prevState = extend({}, s);
extend(s, typeof state==='function' ? state(s, this.props) : state);
const prev = this.prevState = this.state;
if (typeof state === 'function') state = state(prev, this.props);
this.state = extend(extend({}, prev), state);
if (callback) this._renderCallbacks.push(callback);
enqueueRender(this);
},
Expand Down
34 changes: 33 additions & 1 deletion test/browser/lifecycle.js
Expand Up @@ -1186,7 +1186,7 @@ describe('Lifecycle methods', () => {
});


describe('shouldComponentUpdate', () => {
describe('#shouldComponentUpdate', () => {
let setState;

class Should extends Component {
Expand Down Expand Up @@ -1325,6 +1325,38 @@ describe('Lifecycle methods', () => {
});


describe('#setState', () => {
it('should not mutate state, only create new versions', () => {
const stateConstant = {};
let didMount = false;
let componentState;

expect(stateConstant).to.deep.equal({});

class Stateful extends Component {
constructor() {
super(...arguments);
this.state = stateConstant;
}

componentDidMount() {
didMount = true;
this.setState({key: 'value'}, () => {
componentState = this.state;
});
}
}

render(<Stateful />, scratch);
rerender();

expect(didMount).to.equal(true);
expect(componentState).to.deep.equal({key: 'value'});
expect(stateConstant).to.deep.equal({});
});
}),


describe('Lifecycle DOM Timing', () => {
it('should be invoked when dom does (DidMount, WillUnmount) or does not (WillMount, DidUnmount) exist', () => {
let setState;
Expand Down

0 comments on commit ea932dd

Please sign in to comment.