Home > Back-end >  How do I call useQuery in a map function?
How do I call useQuery in a map function?

Time:05-07

I have the below react component which is removing products from a mongodb collection based on the items in the cart. I get this error when I run the code:

Component:

 function AddOrder() {
    const d = new Date();
    let text = d.toString();
    const { currentUser } = useContext(AuthContext);

    const { data, loading, error } = useQuery(queries.GET_USER_BY_ID, {
        fetchPolicy: "network-only",
        variables: {
            id: currentUser.uid,
        },
    });

    const getUserOrders = useQuery(queries.GET_USER_ORDERS, {
        fetchPolicy: "network-only",
        variables: {
            userId: currentUser.uid,
        },
    });

    const [addOrder] = useMutation(queries.ADD_ORDER);
   
    const [editProduct] = useMutation(queries.EDIT_PRODUCT);
    

    if (error) {
        return <h1> error</h1>;
    } else if (loading) {
        return <h1> loading</h1>;
    } else if (data && getUserOrders.data && currentUser && data.getUser.cart.length > 0) {
        let newCart = [];
        for (let i = 0; i < data.getUser.cart.length; i  ) {
            newCart.push({ quantity: data.getUser.cart[i].quantity, _id: data.getUser.cart[i]._id });
        }

        addOrder({
            variables: {
                userId: currentUser.uid,
                status: "ordered",
                createdAt: text,
                products: newCart,
                flag: getUserOrders.data.userOrders.length   1,
            },
        });
        
        newCart.map((x) => {
            let getProd = useQuery(queries.GET_PRODUCTS_BY_ID, {
                fetchPolicy: "network-only",
                variables: {
                    _id : x._id
                },
            });
            let a = getProd.quantity -x.quantity
            editProduct({
                variables: {
                    _id : x._id,
                    quantity: a
                },
            });
        })
    
    }
}
export default AddOrder;

The error I get is:

React Hook "useQuery" cannot be called inside a callback. React Hooks must be called in a React function component or a custom React Hook function

I tried to add the map function as an inner function but that didn't help either. How can I fix this?

CodePudding user response:

Hooks need to be called on every render to be deterministically consistent and React checks for this on every build (and throws an error when detected). If a hook is not in the top/main call stack of your React component, you can expect problems.

What you can do is create another React component that is rendered inside your map function. This React component doesn't need to render anything, you can just add your code and return null.

Try adding this above your component:

function EditProduct = ({ x ) => {
  let getProd = useQuery(queries.GET_PRODUCTS_BY_ID, {
    fetchPolicy: "network-only",
    variables: {
      _id : x._id
    },
  });
  let a = getProd.quantity -x.quantity
  editProduct({
    variables: {
      _id : x._id,
      quantity: a
    },
  });
  return null;
}

Then update your map usage to:

newCart.map((x) => <EditProduct x={x} />)

Understand that on every render of AddOrder that meets your if else condition, the EditProduct component will re-render, which will call the hooks and may cause unintended consequences (such as making the same fetch requests multiple times, if the hooks were designed in such a way). I haven't used your particular hook, so I can't say for certain, but it's something to consider.

  • Related