brand marke
brand marke

Reputation: 459

how to initialize useState with apollo graphql query

How can I use useState and set it with value received from graphql before the component renders?

I tried this:

  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  

  const [me] = useQuery(gql`
    query Me {
      me {
        id
        name
        email
      }
    }
  `);

  useEffect(() => {
    (async () => {
      const { data } = await me();

      if (data) {
        setName(data.me.name);
        setEmail(data.me.email);
      }
    })();
  }, []);

And received this error:

TypeError: Object is not a function
Profile
src/pages/Profile.js:51
  48 | const [currentPasswordValid, setCurrentPasswordValid] = useState(false);
  49 | const [open, setOpen] = useState(false);
  50 | 
> 51 | const [me] = useQuery(gql`
     | ^  52 |   query Me {
  53 |     me {
  54 |       id

Reason I am trying to do this is to set value of form inputs to the current user values:

<TextField value={name} onChange={(e) => setName(e.target.value)} />

Upvotes: 1

Views: 1217

Answers (1)

Felipe
Felipe

Reputation: 7381

It seems that you are using the wrong hook. The useQuery will execute automatically after the component is mounted. It will return a data a loading and an error properties that you can use (there are more of them if you look in the documentation, but these are the basic one).

If you want to fire the query manually you can use the useLazyQuery hook, that will return the properties above and a callback that you can use to execute the query.

With the useQuery you code can look like this:

const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  

  const { data, loading } = useQuery(gql`
    query Me {
      me {
        id
        name
        email
      }
    }
  `);

  if(loading) {
    return <div>loading...</div>;
  }

  return <TextField value={data.me.name} onChange={(e) => setName(e.target.value)} />;

If you prefer to use the lazy query your code can look like this:

  const [name, setName] = useState('');
  const [email, setEmail] = useState('');
  

  const [me, { data }] = useLazyQuery(gql`
    query Me {
      me {
        id
        name
        email
      }
    }
  `);

  useEffect(() => {
    (async () => {
      await me();
    })();
  }, []);

  useEffect(() => {
    if (data) {
      setName(data.me.name);
      setEmail(data.me.email);
    }
  }, [data])

I personally prefer to avoid using lazy queries when I don't have to.

Upvotes: 2

Related Questions