React hooks: maximum depth exceeded

Viewed 738

I a functional component in React, and when I use useState hook to set a value in the return, I am getting an error about Maximum update depth exceeded.

Here is the code:

const TaskDetail = (props) => {
    const [selectedOperatorForTime, setSelectedOperatorForTime] = useState({})
    return (
       <div >  
            <Query query={GET_API_VAL}>
              {({ loading, error, data }) => {
                  let operatorList = {key1: data.value1, key2: data.value2}

                  setSelectedOperatorForTime(operatorList);
       {//rest of the code}

I get the following error

Unhandled Rejection (Error): Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

I tried putting the setState in a separate function instead of having it directly in the return, but I am still seeing the same error. Any guidance? I am using Apollo client (which is what the Query component is for. Unsure how I am causing this to be called repeatedly.

I tried replacing the operatorList with a string, and it works fine. So it seems to be an issue with an object. Anyone experienced this?

1 Answers

If you're using react hooks anyway, you might as well use hooks for apollo-react documented here.

Instead of using the Query component in your JSX, you'd use useQuery at the top of your component like so:

const { loading, error, data } = useQuery(GET_API_VAL);

This would possibly also remove the need for a seperate useState since it always contains the current data.

Your specific example, with no other changes, would look something like this:

const TaskDetail = (props) => {
    const [selectedOperatorForTime, setSelectedOperatorForTime] = useState({});
    const { loading, error, data } = useQuery(GET_API_VAL);

    useEffect(() => {
        // Set selectedOperatorForTime whenever the data changes
        let operatorList = {key1: data.value1, key2: data.value2};
        setSelectedOperatorForTime(operatorList);
    }, [data]);

    return (
       <div >
       {//rest of the code}
Related