@samitouri / QOS-React / commits / 6d4038f0a6

[ShallowRenderer] Queue/rerender on dispatched action after render component with hooks (#14802)

* [shallow-renderer] Rerender on dispatched action out of render

Rodrigo Ribeiro committed Feb 13, 2019 at 12:59 UTC 6d4038f0a638d82e9e528f02cc5a86afb410cf11
2 files changed +39 -3
packages/react-test-renderer/src/ReactShallowRenderer.js
+6 -3
@@ -384,7 +384,7 @@ class ReactShallowRenderer {
384 'an infinite loop.',
385 );
386
387 - if (componentIdentity === this._currentlyRenderingComponent) {
387 + if (componentIdentity === this._previousComponentIdentity) {
388 // This is a render phase update. Stash it in a lazily-created map of
389 // queue -> linked list of updates. After this render pass, we'll restart
390 // and apply the stashed updates on top of the work-in-progress hook.
@@ -408,10 +408,13 @@ class ReactShallowRenderer {
408 }
409 lastRenderPhaseUpdate.next = update;
410 }
411 +
412 + if (!this._rendering) {
413 + this.render(this._element, this._context);
414 + }
415 } else {
416 // This means an update has happened after the function component has
413 - // returned. On the server this is a no-op. In React Fiber, the update
414 - // would be scheduled for a future render.
417 + // returned from a different component.
418 }
419 }
420
packages/react-test-renderer/src/__tests__/ReactShallowRendererHooks-test.js
+33
@@ -90,6 +90,39 @@ describe('ReactShallowRenderer with hooks', () => {
90 );
91 });
92
93 + it('should work with updating a value from useState outside the render', () => {
94 + function SomeComponent({defaultName}) {
95 + const [name, updateName] = React.useState(defaultName);
96 +
97 + return (
98 + <div onClick={() => updateName('Dan')}>
99 + <p>
100 + Your name is: <span>{name}</span>
101 + </p>
102 + </div>
103 + );
104 + }
105 +
106 + const shallowRenderer = createRenderer();
107 + const element = <SomeComponent defaultName={'Dominic'} />;
108 + const result = shallowRenderer.render(element);
109 +
110 + expect(result.props.children).toEqual(
111 + <p>
112 + Your name is: <span>Dominic</span>
113 + </p>,
114 + );
115 +
116 + result.props.onClick();
117 + const updated = shallowRenderer.render(element);
118 +
119 + expect(updated.props.children).toEqual(
120 + <p>
121 + Your name is: <span>Dan</span>
122 + </p>,
123 + );
124 + });
125 +
126 it('should work with useReducer', () => {
127 function reducer(state, action) {
128 switch (action.type) {