UNPKG

react-relay

Version:

A framework for building GraphQL-driven React applications.

175 lines (164 loc) 5.33 kB
/** * 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: createPaginationContainer, } = require('../ReactRelayPaginationContainer'); const React = require('react'); const {graphql} = require('relay-runtime'); /** * Verifies that normal prop type checking, as well as the methods proxying Relay does, is * type-checked correctly on Relay components. */ /* $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 FooComponent extends React.Component { 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 ( <div>{reqLen && optionalProp && optionalFoo && missing && defLen}</div> ); } } // 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 = createPaginationContainer( FooComponent, { viewer: graphql` fragment ReactRelayPaginationContainerFlowtest_viewer on Viewer { account_user { friends(after: $cursor, first: $count) @connection( key: "ReactRelayPaginationContainerFlowtest_viewer__friends" ) { edges { node { __typename } } } } } `, }, { direction: 'forward', getConnectionFromProps: props => props.viewer.account_user.friends, // $FlowFixMe[cannot-spread-interface] getFragmentVariables: (vars, totalCount) => ({ ...vars, count: totalCount, }), getVariables: (props, {count, cursor}) => ({ after: cursor, count, }), query: graphql` query ReactRelayPaginationContainerFlowtestQuery( $count: Int! $cursor: ID ) { viewer { ...ReactRelayPaginationContainerFlowtest_viewer } } `, }, ); module.exports = { checkMissingProp(): React.Node { /** $ShouldBeFlowExpectedError: Foo missing `requiredProp` **/ return <Foo />; }, checkMinimalProps(): React.Node { // All is well return <Foo requiredProp="foo" />; }, checkWrongPropType(): React.Node { /** $ShouldBeFlowExpectedError: Foo1 wrong `requiredProp` type, should be string **/ return <Foo requiredProp={17} />; }, checkWrongOptionalType(): React.Node { /** $ShouldBeFlowExpectedError: Foo wrong `optionalProp` type, should be `{foo: string}` **/ return <Foo optionalProp="wrongType" requiredProp="foo" />; }, checkNullOptionalType(): React.Node { /** $ShouldBeFlowExpectedError: Foo `optionalProp` must be omitted or truthy, not null **/ return <Foo optionalProp={null} requiredProp="foo" />; }, checkWrongDefaultPropType(): React.Node { /** $ShouldBeFlowExpectedError: Foo wrong `defaultProp` type, should be string **/ return <Foo defaultProp={false} requiredProp="foo" />; }, checkAllPossibleProps(): React.Node { // All is well return ( <Foo defaultProp="bar" optionalProp={{foo: 42}} requiredProp="foo" /> ); }, checkMinimalPropSpread(): React.Node { // All is well const props = {requiredProp: 'foo'}; return <Foo {...props} />; }, checkMissingPropSpread(): React.Node { const props = {defaultProp: 'foo'}; /** $ShouldBeFlowExpectedError: Foo missing `requiredProp` with spread **/ return <Foo {...props} />; }, 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 ( <Foo componentRef={ref => { this._fooRef = ref; }} requiredProp="bar" /> ); } } return <ProxyChecker />; }, };