You can wrap a function component with React.memo to shallowly compare its props:

const Button = React.memo((props) => {
  // your component
});
You can wrap a function component with React.memo to shallowly compare its props:

const Button = React.memo((props) => {
  // your component
});
Specifying [count] as a list of dependencies would fix the bug, but would cause the interval to be reset on every change. Effectively, each setInterval would get one chance to execute before being cleared (similar to a setTimeout.) That may not be desirable. To fix this, we can use the functional update form of setState. It lets us specify how the state needs to change without referencing the current state:

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + 1); // ✅ This doesn't depend on `count` variable outside    }, 1000);
    return () => clearInterval(id);
  }, []); // ✅ Our effect doesn't use any variables in the component scope
  return <h1>{count}</h1>;
}
This is a rather convoluted pattern but it shows that you can do this escape hatch optimization if you need it. It’s more bearable if you extract it to a custom Hook:

function Form() {
  const [text, updateText] = useState('');
  // Will be memoized even if `text` changes:
  const handleSubmit = useEventCallback(() => {    alert(text);
  }, [text]);

  return (
    <>
      <input value={text} onChange={e => updateText(e.target.value)} />
      <ExpensiveTree onSubmit={handleSubmit} />
    </>
  );
}

function useEventCallback(fn, dependencies) {  const ref = useRef(() => {
    throw new Error('Cannot call an event handler while rendering.');
  });

  useEffect(() => {
    ref.current = fn;
  }, [fn, ...dependencies]);

  return useCallback(() => {
    const fn = ref.current;
    return fn();
  }, [ref]);
}
The useMemo Hook lets you cache calculations between multiple renders by “remembering” the previous computation:

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
In some rare cases you might need to memoize a callback with useCallback but the memoization doesn’t work very well because the inner function has to be re-created too often. If the function you’re memoizing is an event handler and isn’t used during rendering, you can use ref as an instance variable, and save the last committed value into it manually:

function Form() {
  const [text, updateText] = useState('');
  const textRef = useRef();

  useEffect(() => {
    textRef.current = text; // Write it to the ref  });

  const handleSubmit = useCallback(() => {
    const currentText = textRef.current; // Read it from the ref    alert(currentText);
  }, [textRef]); // Don't recreate handleSubmit like [text] would do

  return (
    <>
      <input value={text} onChange={e => updateText(e.target.value)} />
      <ExpensiveTree onSubmit={handleSubmit} />
    </>
  );
}
In large component trees, an alternative we recommend is to pass down a dispatch function from useReducer via context:

const TodosDispatch = React.createContext(null);

function TodosApp() {
  // Note: `dispatch` won't change between re-renders  const [todos, dispatch] = useReducer(todosReducer);
  return (
    <TodosDispatch.Provider value={dispatch}>
      <DeepTree todos={todos} />
    </TodosDispatch.Provider>
  );
}
Any child in the tree inside TodosApp can use the dispatch function to pass actions up to TodosApp:

function DeepChild(props) {
  // If we want to perform an action, we can get dispatch from context.  const dispatch = useContext(TodosDispatch);
  function handleClick() {
    dispatch({ type: 'add', text: 'hello' });
  }

  return (
    <button onClick={handleClick}>Add todo</button>
  );
}
Sometimes, your effect may be using state that changes too often. You might be tempted to omit that state from a list of dependencies, but that usually leads to bugs:

function Counter() {
  const [count, setCount] = useState(0);

  useEffect(() => {
    const id = setInterval(() => {
      setCount(count + 1); // This effect depends on the `count` state    }, 1000);
    return () => clearInterval(id);
  }, []); // 🔴 Bug: `count` is not specified as a dependency
  return <h1>{count}</h1>;
}
As a last resort, if you want something like this in a class, you can use a ref to hold a mutable variable. Then you can write and read to it. For example:

function Example(props) {
  // Keep latest props in a ref.  const latestProps = useRef(props);  useEffect(() => {    latestProps.current = props;  });
  useEffect(() => {
    function tick() {
      // Read latest props at any time      console.log(latestProps.current);    }

    const id = setInterval(tick, 1000);
    return () => clearInterval(id);
  }, []); // This effect never re-runs}
Conveniently, useMemo also lets you skip an expensive re-render of a child:

function Parent({ a, b }) {
  // Only re-rendered if `a` changes:
  const child1 = useMemo(() => <Child1 a={a} />, [a]);
  // Only re-rendered if `b` changes:
  const child2 = useMemo(() => <Child2 b={b} />, [b]);
  return (
    <>
      {child1}
      {child2}
    </>
  )
}

Recommend

React Hooks FAQ Performance Optimizations What can I do if my effect dependencies change too often?

React Hooks FAQ Performance Optimizations Is it safe to omit functions from the list of dependencies?

React Hooks FAQ From Classes to Hooks How can I measure a DOM node?

React Hooks FAQ From Classes to Hooks Is there something like forceUpdate?

React Hooks FAQ From Classes to Hooks How do I implement getDerivedStateFromProps?

React Hooks FAQ From Classes to Hooks Why am I seeing stale props or state inside my function?

React Hooks FAQ From Classes to Hooks How to get the previous props or state?

React Hooks FAQ From Classes to Hooks Should I use one or many state variables?

React Hooks FAQ From Classes to Hooks Is there something like instance variables?

React Hooks FAQ Adoption Strategy How to test components that use Hooks?

React Forms Controlled Input Null Value

React Forms Handling Multiple Inputs

React Forms The file input Tag

React Forms The select Tag

React Forms The textarea Tag

React Forms Controlled Components

React Forms

Thinking in React Start With A Mock

React Typechecking With PropTypes Function Components

React Typechecking With PropTypes Default Prop Values

React Typechecking With PropTypes Requiring Single Child

React Typechecking With PropTypes PropTypes

React Typechecking With PropTypes

React Lifting State Up Lifting State Up

React Lifting State Up Writing Conversion Functions

React Lifting State Up Adding a Second Input

React Lifting State Up

ReactDOM Reference createPortal()

ReactDOM Reference findDOMNode()

ReactDOM Reference unmountComponentAtNode()

ReactDOM Reference hydrate()

ReactDOM Reference render()

React Release Channels Next Channel Using the Next Channel for Integration Testing

React Uncontrolled Components The file input Tag

React Uncontrolled Components Default Values

React Uncontrolled Components

React CDN Links Why the crossorigin Attribute?

React CDN Links

React Forwarding Refs Displaying a custom name in DevTools

React Forwarding Refs Forwarding refs in higher-order components

React Forwarding Refs Forwarding refs to DOM components

React Using the Effect Hook Tips for Using Effects Tip: Optimizing Performance by Skipping Effects

React Using the Effect Hook Tips for Using Effects Explanation: Why Effects Run on Each Update

React Using the Effect Hook Tips for Using Effects Tip: Use Multiple Effects to Separate Concerns

React Using the Effect Hook Recap

React Using the Effect Hook Effects with Cleanup Example Using Hooks

React Using the Effect Hook Effects with Cleanup Example Using Classes

React Using the Effect Hook Effects Without Cleanup Detailed Explanation

React Using the Effect Hook Effects Without Cleanup Example Using Hooks

React Using the Effect Hook Effects Without Cleanup Example Using Classes

React Using the Effect Hook