/** * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * * @flow strict-local * @format * @oncall relay */ 'use strict'; const { createContainer: createRefetchContainer, } = require('../ReactRelayRefetchContainer'); const React = require('react'); const {graphql} = require('relay-runtime'); /** * Verifies that normal prop type checking works correctly on Relay components. */ class FooComponent extends React.Component<$FlowFixMe> { props: { optionalProp?: {foo: number, ...}, defaultProp: string, requiredProp: string, ... }; static defaultProps: {defaultProp: string} = { defaultProp: 'default', }; getNum(): number { return 42; } render(): React.Node { const reqLen = this.props.requiredProp.length; const optionalProp = this.props.optionalProp; /** $FlowExpectedError: `optionalProp` might be null **/ const optionalFoo = this.props.optionalProp.foo; /** $FlowExpectedError: there is no prop `missingProp` **/ const missing = this.props.missingProp; const defLen = this.props.defaultProp.length; // always a valid string, so no error return (
{reqLen && optionalProp && optionalFoo && missing && defLen}
); } } // Note that we must reassign to a new identifier to make sure flow doesn't propogate types without // the relay type definition doing the work. const Foo = createRefetchContainer<$FlowFixMe, _>( FooComponent, { viewer: graphql` fragment ReactRelayRefetchContainerFlowtest_viewer on Viewer { account_user { friends(after: $cursor, first: $count) @connection( key: "ReactRelayRefetchContainerFlowtest_viewer__friends" ) { edges { node { __typename } } } } } `, }, graphql` query ReactRelayRefetchContainerFlowtestQuery($count: Int!, $cursor: ID) { viewer { ...ReactRelayRefetchContainerFlowtest_viewer } } `, ); module.exports = { checkMissingProp(): React.Node { /** $ShouldBeFlowExpectedError: Foo missing `requiredProp` **/ return ; }, checkMinimalProps(): React.Node { // All is well return ; }, checkWrongPropType(): React.Node { /** $ShouldBeFlowExpectedError: Foo1 wrong `requiredProp` type, should be string **/ return ; }, checkWrongOptionalType(): React.Node { /** $ShouldBeFlowExpectedError: Foo wrong `optionalProp` type, should be `{foo: string}` **/ return ; }, checkNullOptionalType(): React.Node { /** $ShouldBeFlowExpectedError: Foo `optionalProp` must be omitted or truthy, not null **/ return ; }, checkWrongDefaultPropType(): React.Node { /** $ShouldBeFlowExpectedError: Foo wrong `defaultProp` type, should be string **/ return ; }, checkAllPossibleProps(): React.Node { // All is well return ( ); }, checkMinimalPropSpread(): React.Node { // All is well const props = {requiredProp: 'foo'}; return ; }, checkMissingPropSpread(): React.Node { const props = {defaultProp: 'foo'}; /** $ShouldBeFlowExpectedError: Foo missing `requiredProp` with spread **/ return ; }, checkStaticsAndMethodsProxying(): React.Node { /* $FlowFixMe(>=0.53.0) This comment suppresses an * error when upgrading Flow's support for React. Common errors found when * upgrading Flow's React support are documented at * https://fburl.com/eq7bs81w */ class ProxyChecker extends React.PureComponent { _fooRef: ?FooComponent; getString(): string { const ok = this._fooRef ? this._fooRef.getNum() : 'default'; // legit /** $FlowExpectedError: Foo does not have `missingMethod` **/ const bad = this._fooRef ? this._fooRef.missingMethod() : 'default'; /** $FlowExpectedError: Foo `getNum` gives number, but `getString` assumes string **/ return bad ? 'not good' : ok; } render(): React.Node { return ( { this._fooRef = ref; }} requiredProp="bar" /> ); } } return ; }, };