0

By the help of codegen, I have generated custom graphql hooks and types.

    query loadUsers($where: UserFilter) {
  users(where: $where) {
    nodes {
      id
      email
      firstName
      lastName
      phoneNumber
    }
    totalCount
  }
}

export function useLoadUsersLazyQuery(baseOptions?: ApolloReactHooks.LazyQueryHookOptions<LoadUsersQuery, LoadUsersQueryVariables>) {
          return ApolloReactHooks.useLazyQuery<LoadUsersQuery, LoadUsersQueryVariables>(LoadUsersDocument, baseOptions);
        }
export type LoadUsersQueryHookResult = ReturnType<typeof useLoadUsersQuery>;
export type LoadUsersLazyQueryHookResult = ReturnType<typeof useLoadUsersLazyQuery>;
export type LoadUsersQueryResult = ApolloReactCommon.QueryResult<LoadUsersQuery, LoadUsersQueryVariables>;

Now I am trying to use the hook and pass the data into another component like this:

export const UserSearchPage: FunctionComponent = () => {
  const [criteria, setCriteria] = useState('');
  const [searchItem, setSearchItem] = useState('');
  const classes = useStyles();

  const [loadUsers, { data, error }] = useLoadUsersLazyQuery();
  let ShowUsers = () => {
    const where: UserFilter = {};
    switch (Number(criteria)) {
      case 1:
        loadUsers({
          variables: {
            where: where,
          },
        });
        break;
      case 2:
        if (searchItem) {
          where.firstName_contains = searchItem;
          loadUsers({
            variables: {
              //where: { firstName_contains: searchItem },
              where: where,
            },
          });
        }
        break;
      default:
        console.log('default');
    }
  };

  return (
    <div> 
    <div className={classes.container}>
        <Select
          value={criteria}
          onChange={event => setCriteria(event.target.value as string)}
          displayEmpty>
          <MenuItem disabled value="">
            <em>Search By</em>
          </MenuItem>
          <MenuItem value={1}>All</MenuItem>
        </Select>
        <Button className={classes.button} onClick={() => ShowUsers()}>
          {' '}
          <SearchIcon />
          Search
        </Button>
        <br></br>
        {data!==null  && data!==undefined && <UsersFoundList data={data} />}
      </div>
      )
    </div>
  );
};
type UsersFoundListProps = {
    data: LoadUsersQueryResult,
};
export const UsersFoundList: FunctionComponent<UsersFoundListProps> = ({
    data,
}) => {
    console.log('data UserList', data);
    return (
        null
    );
};

For data, I am using the custom type created by codegen. However, I keep getting an error on data that:

<UsersFoundList data={data} />
Type 'LoadUsersQuery' is missing the following properties from type 'QueryResult<LoadUsersQuery, Exact<{ where?: UserFilter | null | undefined; }>>': client, data, loading, networkStatus, and 8 more.

Since the types are generated automatically, this should work as it's working in other cases.

export const LoadUsersDocument = gql`
  query loadUsers($where: UserFilter) {
    users(where: $where) {
      nodes {
        id
        email
        firstName
        lastName
        phoneNumber
      }
      totalCount
    }
  }
`;
  • your passed `data` type is your 'base/root data type', without any resule decorators, just pure expected fields type defined somewhere at the beggining (as base type) of your generators (`LoadUsersDocument` ?) – xadm Jul 31 '20 at 07:56
  • Not sure if I understand your qs correctly but the LoadUsersDocument is the query itself with a gql tag. The LoadUsersQueryResult is defined only once in the whole graphql index file (like I showed in the qs). @xadm –  Jul 31 '20 at 08:27
  • definition of `loadUsersDocument`? type/shape of data it returns? – xadm Jul 31 '20 at 08:31
  • added to qs@xadm –  Jul 31 '20 at 09:09
  • we need only type of 'data` field returned by `useQuery` - nodes: array of user type, totalCount type etc.... `useLoadUsersQuery` defs? – xadm Jul 31 '20 at 09:30
  • I am using useLoadUsersLazyQuery. I have already added the only available types in the qs @xadm –  Jul 31 '20 at 09:39
  • editor doesn't hint type when over `data` (in `useLoadUsersLazyQuery` returned components)? – xadm Jul 31 '20 at 09:47
  • Nope, it leads to the any data type @xadm –  Jul 31 '20 at 09:53

1 Answers1

1

You should have your data shape typed as in docs

const [loadUsers, { data, error }] = useLoadUsersLazyQuery();

If no data type defined by generator then you need to pass down entire result:

const queryResult = useLoadUsersLazyQuery();
const [loadUsers, { data, error }] = queryResult;

then pass it as prop

{data!==null  && data!==undefined && <UsersFoundList data={queryResult} />}

data type in <UsersFoundList/> stays the same:

type UsersFoundListProps = {
  data: LoadUsersQueryResult,
};

but you need to use data. 'prefix' or decompose it:

const {nodes, totalCount} = props.data.data; // instead of usual 'props.data'

nodes will be an array, totalCount a number

xadm
  • 8,219
  • 3
  • 14
  • 25
  • The data type in doc is UserConnection, which is defined by codegen too. I tried using that as well but that also doesn't work. In my previous project, simply something like LoadUsersQueryResult would work. So I am guessing there's something wrong with how I am using codegen :( –  Jul 31 '20 at 10:28
  • error with `type UsersFoundListProps = { data: UserConnection` ? – xadm Jul 31 '20 at 10:54