Updating react context causes infinite render loop

Viewed 471
1 Answers

The problem is in your Predication component. Never call setState() directly inside functional component. If you want to do some work when some props change, you should use useEffect hooks and pass the props as dependencies for it. Never call setState directly inside the function component, you can think never call this.setState() in render() method of a class component.

// Call API when the `input.text` and `input.model` changed
useEffect(() => {
    if (input.text && input.model) {
      console.log("predict");
      predict(input.text, input.model)
        .then((res) => setPrediction(res))
        .catch((e) => <p>Noe gikk galt. Prøv igjen senere</p>);
    }
  }, [input.text, input.model]);

// Never do this, `setPrediction` will make the component re-render and cause the infinite loop.
  // Predict if text
  // if (input.text && input.model) {
  // console.log("predict");
  // predict(input.text, input.model)
  //   .then((res) => setPrediction(res))
  //   .catch((e) => <p>Noe gikk galt. Prøv igjen senere</p>);
  // }

Besides, you should declare the state before using it in your InputContextProvider component.

export const InputContextProvider = (props: any) => {
  const [state, setState] = useState({
    text: "",
    model: "bayes"
  });

  // TODO: Replace any type
  const setInput = (input: any) => {
    setState({ ...state, text: input.text, model: input.model });
  };

  return (
    <InputContext.Provider value={{ ...state, setInput }}>
      {props.children}
    </InputContext.Provider>
  );
};

Codesandbox

Related