Preserve prototype with replaceState
Fixes #3418.
Ben Alpert committed
May 8, 2015 at 12:04 UTC
d7de12fbd8737ab491a2836e7f2ed47ad693eda5
2 files changed
+69
src/core/ReactCompositeComponent.js
+4
@@ -623,6 +623,10 @@ var ReactCompositeComponentMixin = {
623
return inst.state;
624
}
625
626
+ if (replace && queue.length === 1) {
627
+ return queue[0];
628
+ }
629
+
630
var nextState = assign({}, replace ? queue[0] : inst.state);
631
for (var i = replace ? 1 : 0; i < queue.length; i++) {
632
var partial = queue[i];
src/core/__tests__/ReactCompositeComponent-test.js
+65
@@ -877,4 +877,69 @@ describe('ReactCompositeComponent', function() {
877
expect(console.error.argsForCall.length).toBe(0);
878
});
879
880
+ it('should replace state', function() {
881
+ var Moo = React.createClass({
882
+ getInitialState: function() {
883
+ return {x: 1};
884
+ },
885
+ render: function() {
886
+ return <div />;
887
+ }
888
+ });
889
+
890
+ var moo = ReactTestUtils.renderIntoDocument(<Moo />);
891
+ moo.replaceState({y: 2});
892
+ expect('x' in moo.state).toBe(false);
893
+ expect(moo.state.y).toBe(2);
894
+ });
895
+
896
+ it('should support objects with prototypes as state', function() {
897
+ var NotActuallyImmutable = function(str) {
898
+ this.str = str;
899
+ };
900
+ NotActuallyImmutable.prototype.amIImmutable = function() {
901
+ return true;
902
+ };
903
+ var Moo = React.createClass({
904
+ getInitialState: function() {
905
+ return new NotActuallyImmutable('first');
906
+ },
907
+ render: function() {
908
+ return <div />;
909
+ }
910
+ });
911
+
912
+ var moo = ReactTestUtils.renderIntoDocument(<Moo />);
913
+ expect(moo.state.str).toBe('first');
914
+ expect(moo.state.amIImmutable()).toBe(true);
915
+
916
+ var secondState = new NotActuallyImmutable('second');
917
+ moo.replaceState(secondState);
918
+ expect(moo.state.str).toBe('second');
919
+ expect(moo.state.amIImmutable()).toBe(true);
920
+ expect(moo.state).toBe(secondState);
921
+
922
+ moo.setState({str: 'third'});
923
+ expect(moo.state.str).toBe('third');
924
+ // Here we lose the prototype.
925
+ expect(moo.state.amIImmutable).toBe(undefined);
926
+
927
+ // When more than one state update is enqueued, we have the same behavior
928
+ var fifthState = new NotActuallyImmutable('fifth');
929
+ ReactUpdates.batchedUpdates(function() {
930
+ moo.setState({str: 'fourth'});
931
+ moo.replaceState(fifthState);
932
+ });
933
+ expect(moo.state).toBe(fifthState);
934
+
935
+ // When more than one state update is enqueued, we have the same behavior
936
+ var sixthState = new NotActuallyImmutable('sixth');
937
+ ReactUpdates.batchedUpdates(function() {
938
+ moo.replaceState(sixthState);
939
+ moo.setState({str: 'seventh'});
940
+ });
941
+ expect(moo.state.str).toBe('seventh');
942
+ expect(moo.state.amIImmutable).toBe(undefined);
943
+ });
944
+
945
});