Você já se perguntou por que atualizar uma lista no contexto do React acaba re-renderizando componentes que nem mesmo deveriam ser afetados? Vamos entender isso com um exemplo simples.
Imagine que você tenha o seguinte código:
import { createContext, useReducer } from 'react';
import { getInitialItems } from './lib/items';
import { reducer } from './lib/reducer';
const ItemsContext = createContext({});
const ItemsProvider = ({ children }) => {
const [items, dispatch] = useReducer(reducer, getInitialItems());
return (
<ItemsContext.Provider value={{ items, dispatch }}>
{children}
</ItemsContext.Provider>
);
}
export default ItemsProvider;
No código acima, temos dois valores no mesmo objeto:
<ItemsContext.Provider value={{ items, dispatch }}>
Aqui está o detalhe: mesmo que items
ou dispatch
não tenham mudado, o objeto inteiro é recriado a cada renderização. Como o React faz a comparação por referência, ele assume que algo mudou e dispara re-renderizações em todos os componentes que consomem esse contexto.
Resultado? Re-renderizações desnecessárias e, em aplicações maiores, queda de performance.
A solução: separe o que muda do que não muda
Para resolver esse problema, podemos dividir o contexto em dois contextos separados:
- Um contexto para valores que mudam (como
items
). - Um contexto para valores que não mudam (como
dispatch
).
Veja como isso fica:
import { createContext, useReducer } from 'react';
import { getInitialItems } from './lib/items';
import { reducer } from './lib/reducer';
const ItemsContext = createContext({});
const ActionsContext = createContext({});
const ItemsProvider = ({ children }) => {
const [items, dispatch] = useReducer(reducer, getInitialItems());
return (
<ActionsContext.Provider value={dispatch}>
<ItemsContext.Provider value={items}>
{children}
</ItemsContext.Provider>
</ActionsContext.Provider>
);
}
export default ItemsProvider;
Por que separar os contextos melhora a performance?
A mágica acontece porque agora:
ActionsContext
(que contémdispatch
) não muda, então os componentes que o consomem não re-renderizam desnecessariamente.ItemsContext
contém apenas o valoritems
, que será atualizado somente quando necessário.
Além disso, a ordem dos providers é importante. Como todos os “pais” no React disparam re-renderizações nos filhos, ao colocar o que não muda fora do que muda, evitamos que a atualização de um contexto afete o outro.
Conclusão
Separar o que muda do que não muda no React Context é uma técnica poderosa para evitar re-renderizações desnecessárias e melhorar a performance da sua aplicação.
Seguindo essa prática, suas aplicações React ficarão mais rápidas, eficientes e fáceis de manter!