React.js: arrays and "Critical assumptions about the merge functions have been violated" error

StackOverflow https://stackoverflow.com/questions/21902157

  •  14-10-2022
  •  | 
  •  

Question

http://jsfiddle.net/NV/f54Xr/

/**
 * @jsx React.DOM
 */

var Dummy = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function() {
        return [42, 54];
    },
    render: function() {
        return <div>
            {this.state.map(this.renderItem)}
            <pre>{JSON.stringify(this.state, null, 2)}</pre>
        </div>
    },
    renderItem: function(item, i) {
        return <div>
            <input type="number" valueLink={this.linkState(i)}/>
        </div>
    }
});


React.renderComponent(
    <Dummy/>,
    document.body
);

When I’m changing numbers in the input fields React throws:

Uncaught Error: Invariant Violation: Critical assumptions about the merge functions have been violated. This is the fault of the merge functions themselves, not necessarily the callers.

Is it a bug in React? Is merging arrays not working?

No correct solution

OTHER TIPS

Your state is an array.

I didn't see anything in the React doc mentioning the LinkedStateMixin mixin could link an input to an array index.

What happens is probably:

  • Your initial state is [42, 54]
  • If you modify item at index 0, the LinkedStateMixin creates a new state { 0: 43 }

As setState() doesn't override an existing state but merges the new state into the existing state (because you only update one input at a time), then React is trying to merge a JSON object into a JS array. Which is weird :)

Actually your initial values are displayed correctly because both array[index] and object[key] works the same.

I don't think React support arrays well for now but it's worth opening a pull request maybe.

For now you can try to use objects like this:

http://jsfiddle.net/f54Xr/3/

var Dummy = React.createClass({
    mixins: [React.addons.LinkedStateMixin],
    getInitialState: function() {
        return {0: 42, 1: 54};
    },
    render: function() {
        return <div>
            {Object.keys(this.state).map(this.renderItem)}
            <pre>{JSON.stringify(this.state, null, 2)}</pre>
        </div>
    },
    renderItem: function(key) {
        return <div>
            <input type="number" valueLink={this.linkState(key)}/>
        </div>
    }
}); 

By the way you may try to create your own LinkedStateMixin to link to an array index, has you have done there:

React.js 2-way bindings: two-levels deep path in valueLink

I just wonder if it is possible in React to have state = [42, 54] and then setState([undefined, 55]) to finally have state = [42, 55], please tell us :)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top