logoESLint React
Rules

no-unstable-context-value

Prevents non-stable values (i.e., object literals) from being used as a value for `Context.Provider`.

Full Name in eslint-plugin-react-x

react-x/no-unstable-context-value

Full Name in @eslint-react/eslint-plugin

@eslint-react/no-unstable-context-value

Presets

strict strict-typescript strict-type-checked

Rule Details

React will re-render all consumers of a context whenever the context value changes, and if the value is not stable this can lead to unnecessary re-renders.

Common Violations

Invalid

import React from "react";

const MyContext = React.createContext({});

function MyComponentProvider() {
  return (
    <MyContext.Provider value={{ foo: "bar" }}>
      {/*                      ^^^^^^^^^^^^^^ */}
      {/*                      - An 'Object literal' passed as the value prop to the context provider should not be constructed. It will change on every render. Consider wrapping it in a useMemo hook. */}
      <ExampleConsumer />
    </MyContext.Provider>
  );
}

Valid

import React, { useMemo } from "react";

const MyContext = React.createContext({});

const value = { foo: "bar" };

function MyComponentProvider() {
  return (
    <MyContext.Provider value={value}>
      <ExampleConsumer />
    </MyContext.Provider>
  );
}
import React from "react";

const MyContext = React.createContext({});

function MyComponentProvider() {
  "use memo";
  return (
    <MyContext.Provider value={{ foo: "bar" }}>
      <ExampleConsumer />
    </MyContext.Provider>
  );
}

Legitimate Uses

React Context and all its child nodes and consumers are re-rendered whenever the value prop changes. Because each JavaScript object carries its own identity, things like object expressions ({foo: 'bar'}) or function expressions get a new identity on every run through the component. This makes the context think it has received a new object and can cause needless re-renders and unintended consequences.

This can be a large performance hit because not only will it cause the context providers and consumers to re-render with all the elements in their subtree, the processing for the tree scan React does to render the provider and find consumers is also wasted.

Resources

Further Reading


See Also

On this page