Search code examples
reactjsapollouse-effect

Run Apollo mutation on first render with useEffect


I have a form in a MUI dialogue. I want to create an order when the dialogue first opens. I thought useEffect with empty dependency would do that but I can't seem to figure out why it doesn't let the mutation resolve before the setState.

  const [createOrder] = useMutation(CREATE_ORDER);

  const [activeOrder, setActiveOrder] = useState({});

  useEffect(() => {
    const newOrder = async () => {
      await createOrder({
        variables: {
          order: {
            type,
            table,
          },
        },
        refetchQueries: [{ query: ORDERS_QUERY }],
      });
    };

    setActiveOrder(newOrder);
  }, []);

  console.log(activeOrder); // gives me Promise{<fulfilled>: undefined}

Also, is the only way to get rid of the missing dependency warning with // eslint-disable-next-line? If I wrap my function in a useCallback to prevent render loop and add the dependencies requested, then useCallback gives me an error that the dependencies are unknown.


Solution

  • your problem is here setActiveOrder(newOrder);

    1. setActiveOrder can accept function as an argument and call it;
    2. newOrder is async function. async function always returns promise;

    solution:

    /*
    maybe your don't need activeOrder, check data from result
    https://www.apollographql.com/docs/react/data/mutations/#result
    */
    const [createOrder, { data }] = useMutation(CREATE_ORDER, {
      // https://www.apollographql.com/docs/react/data/mutations/#options
      variables: { type, table },
      refetchQueries: [{ query: ORDERS_QUERY }],
    });
    const [activeOrder, setActiveOrder] = useState({});
        
    useEffect(() => {
      createOrder().then((res) => {
        setActiveOrder(res);
      });
        
    }, [createOrder]);
    
    useEffect(() => console.log('data:\n', data), [data]);
    useEffect(() => console.log('activeOrder:\n', activeOrder), [activeOrder]);