diff --git a/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js b/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js index 243232f1b83bf..06eba20e6cfe7 100644 --- a/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js +++ b/packages/react-reconciler/src/__tests__/useMutableSource-test.internal.js @@ -1730,6 +1730,53 @@ describe('useMutableSource', () => { param => param.version, ); + let mutatedValueInRender = 0; + function MutateDuringRead() { + const value = useMutableSource( + mutableSource, + defaultGetSnapshot, + defaultSubscribe, + ); + Scheduler.unstable_yieldValue('MutateDuringRead:' + value); + // Note that mutating an exeternal value during render is a side effect and is not supported. + source.value = mutatedValueInRender++; + return null; + } + + expect(() => { + expect(() => { + act(() => { + ReactNoop.render(); + }); + }).toThrow( + 'Cannot read from mutable source during the current render without tearing. This may be a bug in React. Please file an issue.', + ); + }).toWarnDev([ + // Warns twice because of the retry-on-error render pass. Should + // consider only warning during the first attempt, not during the + // retry. Or maybe vice versa. + 'A mutable source was mutated while the MutateDuringRead component was rendering. This is not supported. ' + + 'Move any mutations into event handlers or effects.\n' + + ' in MutateDuringRead (at **)', + 'A mutable source was mutated while the MutateDuringRead component was rendering. This is not supported. ' + + 'Move any mutations into event handlers or effects.\n' + + ' in MutateDuringRead (at **)', + ]); + + expect(Scheduler).toHaveYielded([ + 'MutateDuringRead:initial', + 'MutateDuringRead:0', + ]); + }); + + // @gate experimental + it('should throw if a mutable source is mutated during render (legacy mode)', () => { + const source = createSource('initial'); + const mutableSource = createMutableSource( + source, + param => param.version, + ); + function MutateDuringRead() { const value = useMutableSource( mutableSource,