Validate props on context providers (#12658)
* checkPropTypes in updateContextProvider * invalid “prop” * `type not `types` .. :l * test * don’t need extra check with no spelling mistake (: * change error message to specifically address provider * don’t need class, add extra render to make sure good props go through * nitpicky rename * prettier * switch to `Context.Provider` * add stack to warning, add extra undefined check * separate dev check * add stack to test * more efficient * remove unused function * prettier * const to top
Nicole Levy committed
Apr 22, 2018 at 08:39 UTC
5dcf93d146ccde90af2c442d6cb32b29efddb46b
2 files changed
+39
packages/react-reconciler/src/ReactFiberBeginWork.js
+17
@@ -16,6 +16,7 @@ import type {NewContext} from './ReactFiberNewContext';
16
import type {HydrationContext} from './ReactFiberHydrationContext';
17
import type {FiberRoot} from './ReactFiberRoot';
18
import type {ExpirationTime} from './ReactFiberExpirationTime';
19
+import checkPropTypes from 'prop-types/checkPropTypes';
20
21
import {
22
IndeterminateComponent,
@@ -63,6 +64,8 @@ import {NoWork, Never} from './ReactFiberExpirationTime';
64
import {AsyncMode, StrictMode} from './ReactTypeOfMode';
65
import MAX_SIGNED_31_BIT_INT from './maxSigned31BitInt';
66
67
+const {getCurrentFiberStackAddendum} = ReactDebugCurrentFiber;
68
+
69
let didWarnAboutBadClass;
70
let didWarnAboutGetDerivedStateOnFunctionalComponent;
71
let didWarnAboutStatelessRefs;
@@ -885,6 +888,20 @@ export default function<T, P, I, TI, HI, PI, C, CC, CX, PL>(
888
const newValue = newProps.value;
889
workInProgress.memoizedProps = newProps;
890
891
+ if (__DEV__) {
892
+ const providerPropTypes = workInProgress.type.propTypes;
893
+
894
+ if (providerPropTypes) {
895
+ checkPropTypes(
896
+ providerPropTypes,
897
+ newProps,
898
+ 'prop',
899
+ 'Context.Provider',
900
+ getCurrentFiberStackAddendum,
901
+ );
902
+ }
903
+ }
904
+
905
let changedBits: number;
906
if (oldProps === null) {
907
// Initial render
packages/react/src/__tests__/ReactContextValidator-test.js
+22
@@ -225,6 +225,28 @@ describe('ReactContextValidator', () => {
225
ReactTestUtils.renderIntoDocument(<Component testContext={{foo: 'foo'}} />);
226
});
227
228
+ it('warns of incorrect prop types on context provider', () => {
229
+ const TestContext = React.createContext();
230
+
231
+ TestContext.Provider.propTypes = {
232
+ value: PropTypes.string.isRequired,
233
+ };
234
+
235
+ ReactTestUtils.renderIntoDocument(<TestContext.Provider value="val" />);
236
+
237
+ class Component extends React.Component {
238
+ render() {
239
+ return <TestContext.Provider />;
240
+ }
241
+ }
242
+
243
+ expect(() => ReactTestUtils.renderIntoDocument(<Component />)).toWarnDev(
244
+ 'Warning: Failed prop type: The prop `value` is marked as required in ' +
245
+ '`Context.Provider`, but its value is `undefined`.\n' +
246
+ ' in Component (at **)',
247
+ );
248
+ });
249
+
250
// TODO (bvaughn) Remove this test and the associated behavior in the future.
251
// It has only been added in Fiber to match the (unintentional) behavior in Stack.
252
it('should warn (but not error) if getChildContext method is missing', () => {