How to solve problem with too many re-renders in context?

There is no render bailout for context consumers (v17).

Here is a demonstration, where the Consumer will always re-render just because he is a Context Consumer, even though he doesn’t consume anything.

import React, { useState, useContext, useMemo } from "react";
import ReactDOM from "react-dom";

// People wonder why the component gets render although the used value didn't change
const Context = React.createContext();

const Provider = ({ children }) => {
  const [counter, setCounter] = useState(0);
  const value = useMemo(() => {
    const count = () => setCounter(p => p + 1);
    return [counter, count];
  }, [counter]);
  return <Context.Provider value={value}>{children}</Context.Provider>;

const Consumer = React.memo(() => {
  return <>Consumer</>;

const ContextChanger = () => {
  const [, count] = useContext(Context);
  return <button onClick={count}>Count</button>;

const App = () => {
  return (
      <Consumer />
      <ContextChanger />

    <App />

Edit Context API Problem

To fix it:

  • Use a single context for each consumed value. Meaning that context holds a single value, (and no, there is no problem with multiple contexts in an application).
  • Use a state management solution like Recoil.js, Redux, MobX, etc. (although it might be overkill, think good about app design beforehand).
  • Minor optimization can be achieved by memoizing Provider’s values with useMemo.

Leave a Comment