Change:
I'm still learning React, so it's possible I'm misunderstanding something. I'm trying to use React with , and hit a stumbling block, by upgrading to React 0.13. There is on the repository, that explains how to use immutable as a react state, and it provides the following example (I transpiled it to ES3): This works great in 0.12, but in 0.13, you will receive the following error when clicking on the div: Putting a breakpoint on the error, and inspecting with a debugger reveals that all the methods on have disappeared. Is this the expected behavior in 0.13?
should be a plain object, you're not allowed to put classes in there.
So the wiki page I linked to is incorrect? It would make working with (and probably other immutable implementions) a pita, since you would have to pack/unpack the object every time you store/retrieve it.
Seems so... cc
I encountered the same thing in 0.12, storing an immutable-js object on the state directly clobbers it,but simply putting it under an attribute works fine. E.g. .
I am experiencing this after upgrading to 0.13 as well. It didn't seem to be a problem in react 0.12. It seems to almost make sense that state could be an immutable object since equality comparison is cheap. I could nest my state object under state ( yuck) but it seems like it would create a lot of boilerplate code that I didn't need in 0.12
I think you can +1 in
Yeah this bit me bad... I used an as all my state and not a plain object, which worked absolutely great in 0.12 and broke in 0.13. This forces me to add a bunch of useless vanilla objects with a single child prop to hold my immutable map.
Since I was working with a simple map structure, toObject saved me... e.g. Not sure how well this work with more complex object structures however.
Has there been any movement on this? My project has been on hold since I don't know if I should: a.) stay on React 0.12 where I could use Immutable maps for state. b.) Move all my immutable maps to child of a single-item map. or c.) leave things as they are and this will be supported in the future.
AFAIK this is not going to change. Personally I still don't understand why people want to put third-party objects as state, I don't see what benefit there is. What's wrong with just using ?
For me there were two main advantages. ) My stores already deal in immutable hashes, With react 0.12 I didn't have to bother converting them ) Deep comparison for updates is simple with immutable objects. With react 0.12 when you setState with an immutable object, if any of it's contents had changed, it would re-render. If it was the same, it would not. Comparing immutable objects is cheap. Deep comparing hashes is not. There is more upfront cost with the immutable objects, but they are way easier to reason about wether or not they have changed. If there is definitely no plan to support this then I suppose the best plan of action is to to_js everything and manually deep compare?
There is movement on which would get rid of replaceState and add better immutable-js support (and perhaps other libraries) in the core. However, it was not our intention to break the old behavior of replaceState in 0.13 so this seems like a bug to me. Do we maybe want to patch release this if there is an easy fix?
1) I can't speak for this, but using a store's data for the singular state object seems rather limiting, you're now unable to include any other stores or introduce any other locally relevant state for the component right? 2) Is straight-forward with objects as well, immutability is not a concept that is unique to immutable-js. Depending on the underlying behaviors you can use just or a simple reusable shallow equality test with plain objects too. But does actually intend to allow replacing the "state object" vs just simply understanding how to iterate over generic maps/sets?
) Yes, I do have some components that use data from multiple stores, and those end up as different elements under a hash. When I have a component that only uses the data from one store, it is sort of silly to have it nested as a single element in a hash. ) "you can use just === or a simple reusable shallow equality test with plain objects too" is my point exactly, usually my objects are just one level deep and this is fine. I sometimes they are not though and with Immutable-js objects I can use === with deeply nested objects. If I use immutable-js for everything, I don't have to worry about it.
not sure that it will be the cleanest thing. This is a result of your changes . Right now we just have a but we don't know what each thing in the queue is (did it come from a or ). We could wrap each item in the queue so we know what it came from, so instead of we have . That would allow us to stack and calls (which I don't think we actually handle correctly now). But the simplest case where you're only using , we can probably just change this line:
We could take something in 0.13.4 (not 0.13.3, shipping that today). But it needs to bake first. Both changes I mentioned would change behavior so there's some risk. The first is more complete, the latter trades 1 bug for a slightly less bad bug (setState(), replaceState() in the same update queue will result in the object passed to setState being used as the replacement since we only have a single pendingReplace flag)
Actually, this came from . There is a simple fix: Because the queue is emptied for every replaceState, since nothing earlier in the queue could've affected the result:
Ah, truth. is fixing and it's small and let's just take it in 0.13.3 so we don't have to do another patch release so soon after.
So, the issue was fixed in , but what about components using ? I'm seeing this when I use
setState merges. Using a non-plain object with it isn't supported. You can put whatever object you want on an inner state key (, , etc.).

Discussion:
return inst.state; } <ins> if (replace && queue.length === 1) { return queue[0]; } </ins> var nextState = assign({}, replace ? queue[0] : inst.state); for (var i = replace ? 1 : 0; i < queue.length; i++) { var partial = queue[i];

expect(console.error.argsForCall.length).toBe(0); }); <ins> it('should replace state', function() { var Moo = React.createClass({ getInitialState: function() { return {x: 1}; }, render: function() { return <div />; } }); var moo = ReactTestUtils.renderIntoDocument(<Moo />); moo.replaceState({y: 2}); expect('x' in moo.state).toBe(false); expect(moo.state.y).toBe(2); }); it('should support objects with prototypes as state', function() { var NotActuallyImmutable = function(str) { this.str = str; }; NotActuallyImmutable.prototype.amIImmutable = function() { return true; }; var Moo = React.createClass({ getInitialState: function() { return new NotActuallyImmutable('first'); }, render: function() { return <div />; } }); var moo = ReactTestUtils.renderIntoDocument(<Moo />); expect(moo.state.str).toBe('first'); expect(moo.state.amIImmutable()).toBe(true); var secondState = new NotActuallyImmutable('second'); moo.replaceState(secondState); expect(moo.state.str).toBe('second'); expect(moo.state.amIImmutable()).toBe(true); expect(moo.state).toBe(secondState); moo.setState({str: 'third'}); expect(moo.state.str).toBe('third'); // Here we lose the prototype. expect(moo.state.amIImmutable).toBe(undefined); // When more than one state update is enqueued, we have the same behavior var fifthState = new NotActuallyImmutable('fifth'); ReactUpdates.batchedUpdates(function() { moo.setState({str: 'fourth'}); moo.replaceState(fifthState); }); expect(moo.state).toBe(fifthState); // When more than one state update is enqueued, we have the same behavior var sixthState = new NotActuallyImmutable('sixth'); ReactUpdates.batchedUpdates(function() { moo.replaceState(sixthState); moo.setState({str: 'seventh'}); }); expect(moo.state.str).toBe('seventh'); expect(moo.state.amIImmutable).toBe(undefined); }); </ins> });