@@ -49,6 +49,8 @@ let renderPhaseUpdates: Map<UpdateQueue<any>, Update<any>> | null = null;
49
49
let numberOfReRenders : number = 0 ;
50
50
const RE_RENDER_LIMIT = 25 ;
51
51
52
+ let shouldWarnAboutReadingContextInDEV = false ;
53
+
52
54
// In DEV, this is the name of the currently executing primitive hook
53
55
let currentHookNameInDev : ?string ;
54
56
@@ -137,6 +139,9 @@ function createWorkInProgressHook(): Hook {
137
139
138
140
export function prepareToUseHooks ( componentIdentity : Object ) : void {
139
141
currentlyRenderingComponent = componentIdentity ;
142
+ if ( __DEV__ ) {
143
+ shouldWarnAboutReadingContextInDEV = false ;
144
+ }
140
145
141
146
// The following should have already been reset
142
147
// didScheduleRenderPhaseUpdate = false;
@@ -173,6 +178,9 @@ export function finishHooks(
173
178
numberOfReRenders = 0 ;
174
179
renderPhaseUpdates = null ;
175
180
workInProgressHook = null ;
181
+ if ( __DEV__ ) {
182
+ shouldWarnAboutReadingContextInDEV = false ;
183
+ }
176
184
177
185
// These were reset above
178
186
// currentlyRenderingComponent = null;
@@ -191,6 +199,15 @@ function readContext<T>(
191
199
): T {
192
200
let threadID = currentThreadID ;
193
201
validateContextBounds ( context , threadID ) ;
202
+ if ( __DEV__ ) {
203
+ warning (
204
+ ! shouldWarnAboutReadingContextInDEV ,
205
+ 'Context can only be read while React is rendering. ' +
206
+ 'In classes, you can read it in the render method or getDerivedStateFromProps. ' +
207
+ 'In function components, you can read it directly in the function body, but not ' +
208
+ 'inside Hooks like useReducer() or useMemo().' ,
209
+ ) ;
210
+ }
194
211
return context [ threadID ] ;
195
212
}
196
213
@@ -255,7 +272,13 @@ export function useReducer<S, A>(
255
272
const action = update . action ;
256
273
// Temporarily clear to forbid calling Hooks.
257
274
currentlyRenderingComponent = null ;
275
+ if ( __DEV__ ) {
276
+ shouldWarnAboutReadingContextInDEV = true ;
277
+ }
258
278
newState = reducer ( newState , action ) ;
279
+ if ( __DEV__ ) {
280
+ shouldWarnAboutReadingContextInDEV = false ;
281
+ }
259
282
currentlyRenderingComponent = component ;
260
283
update = update . next ;
261
284
} while ( update !== null ) ;
@@ -311,8 +334,14 @@ function useMemo<T>(nextCreate: () => T, deps: Array<mixed> | void | null): T {
311
334
312
335
// Temporarily clear to forbid calling Hooks.
313
336
currentlyRenderingComponent = null ;
337
+ if ( __DEV__ ) {
338
+ shouldWarnAboutReadingContextInDEV = true ;
339
+ }
314
340
const nextValue = nextCreate();
315
341
currentlyRenderingComponent = component;
342
+ if (__DEV__) {
343
+ shouldWarnAboutReadingContextInDEV = false ;
344
+ }
316
345
workInProgressHook.memoizedState = [nextValue, nextDeps];
317
346
return nextValue;
318
347
}
0 commit comments