title: React context with hooks prevent re render
body: <p>I use React context with hooks as a state manager for my React app. Every time the value changes in the store, all the components re-render. </p>
  
  <p>Is there any way to prevent React component to re-render?</p>
  
  <p>Store config:</p>
  
  <pre><code>import React, { useReducer } from "react";
  import rootReducer from "./reducers/rootReducer";
  
  export const ApiContext = React.createContext();
  
  export const Provider = ({ children }) =&gt; {
    const [state, dispatch] = useReducer(rootReducer, {});
  
    return (
      &lt;ApiContext.Provider value={{ ...state, dispatch }}&gt;
        {children}
      &lt;/ApiContext.Provider&gt;
    );
  };
  </code></pre>
  
  <p>An example of a reducer:</p>
  
  <pre><code>import * as types from "./../actionTypes";
  
  const initialState = {
    fetchedBooks: null
  };
  
  const bookReducer = (state = initialState, action) =&gt; {
    switch (action.type) {
      case types.GET_BOOKS:
        return { ...state, fetchedBooks: action.payload };
  
      default:
        return state;
    }
  };
  
  export default bookReducer;
  </code></pre>
  
  <p>Root reducer, that can combine as many reducers, as possible:</p>
  
  <pre><code>import userReducer from "./userReducer";
  import bookReducer from "./bookReducer";
  
  const rootReducer = ({ users, books }, action) =&gt; ({
    users: userReducer(users, action),
    books: bookReducer(books, action)
  });
  </code></pre>
  
  <p>An example of an action:</p>
  
  <pre><code>import * as types from "../actionTypes";
  
  export const getBooks = async dispatch =&gt; {
    const response = await fetch("https://jsonplaceholder.typicode.com/todos/1", {
      method: "GET"
    });
  
    const payload = await response.json();
  
    dispatch({
      type: types.GET_BOOKS,
      payload
    });
  };
  export default rootReducer;
  </code></pre>
  
  <p>And here's the book component:</p>
  
  <pre><code>import React, { useContext, useEffect } from "react";
  import { ApiContext } from "../../store/StoreProvider";
  import { getBooks } from "../../store/actions/bookActions";
  
  const Books = () =&gt; {
    const { dispatch, books } = useContext(ApiContext);
    const contextValue = useContext(ApiContext);
  
    useEffect(() =&gt; {
      setTimeout(() =&gt; {
        getBooks(dispatch);
      }, 1000);
    }, [dispatch]);
  
    console.log(contextValue);
  
    return (
      &lt;ApiContext.Consumer&gt;
        {value =&gt;
          value.books ? (
            &lt;div&gt;
              {value.books &amp;&amp;
                value.books.fetchedBooks &amp;&amp;
                value.books.fetchedBooks.title}
            &lt;/div&gt;
          ) : (
            &lt;div&gt;Loading...&lt;/div&gt;
          )
        }
      &lt;/ApiContext.Consumer&gt;
    );
  };
  
  export default Books;
  </code></pre>
  
  <p>When the value changes in Books component, another my component Users re-renders:</p>
  
  <pre><code>import React, { useContext, useEffect } from "react";
  import { ApiContext } from "../../store/StoreProvider";
  import { getUsers } from "../../store/actions/userActions";
  
  const Users = () =&gt; {
    const { dispatch, users } = useContext(ApiContext);
    const contextValue = useContext(ApiContext);
  
    useEffect(() =&gt; {
      getUsers(true, dispatch);
    }, [dispatch]);
  
    console.log(contextValue, "Value from store");
  
    return &lt;div&gt;Users&lt;/div&gt;;
  };
  
  export default Users;
  </code></pre>
  
  <p>What's the best way to optimize context re-renders? Thanks in advance!</p>