Vamos ver alguns padrões comuns e como evitá-los fará seu código mais perfomático. Vamos explorar isso abaixo, mas antes alguns pontos importantes:
O hook useSelector permite extrair/selecionar dados do Redux.
O selector pode retornar qualquer valor como resultado, não apenas um objeto.
Quando uma action é disparada, useSelector() comparará o valor retornado anteriormente e o valor atual retornado. Se eles forem diferentes, o. componente será forçado a re-renderizar. Se eles forem iguais, o componente não re-renderizará.
Vamos lá:
UseSelector: retornando sempre um novo objeto e desestruturando.
Esse equívoco geralmente ocorre, pois achamos que chamar vários useSelectors é ruim, e isso não é verdade. Você pode e deve chamar vários useSelectors se necessário.
Evite:
/**
* ❌ Atenção: sempre forçará seu componente a re-renderizar e será preciso usar
* shalowEqual desnecessariamente
*/
const { name, token } = useSelector((state) => ({
name: state.user.name,
token: state.auth.token
}));
Faça:
/**
* ✅ Bom: somente forçará um render se e somente se o name ou token mudar.
*/
const name = useSelector((state) => state.user.name);
const token = useSelector((state) => state.auth.token);
useSelector: retornando um objeto, mas você precisa somente de algumas propriedades desse objeto:
Evite:
/**
* ❌ Atenção:
* Força um re-render sempre que o objeto user mudar
*/
const user = useSelector((state) => state.user);
const { name, website } = user;
Faça:
/**
* ✅ Bom:
* re-renderiza somente se name ou website forem diferentes
*/
const name = useSelector((state) => state.user.name);
const website = useSelector((state) => state.user.website);
useSelector: usando Array.map, Array.filter etc. no seu selector.
Desde que esses métodos sempre retornam objetos diferentes, isso fará o useSelector forçar seu componente a sempre re-renderizar.
Evite:
/**
* ❌ Atenção:
* Renderizará sempre, pois o selector sempre retorna um novo objeto;
* map, filter sempre retornam novo objeto.
*/
const hobbies = useSelector((state) =>
state.user.hobbies.filter((hobbie) => hobbie)
);
}
Faça:
/**
* ❌ Melhor:
* Renderizará sempre, pois o selector sempre retorna um novo objeto;
* map, filter sempre retornam novo objeto.
*/
const hobbies = useSelector((state) => state.user.hobbies,
shalowEqual);
}
const filteredHobbies = hobbies.filter((hobbie) => hobbie)
Extra tip: hooks customizados
Desde que seus hooks encapsulam lógicas, é importante prestar atenção ao seus states internos. Se um state interno de um hook customizado mudar, este hook forçará um re-render no componente que o usa.
function Blog(){
/**
* ❗️ Se o state de useBlogName mudar, Blog re-renderizará.
*/
const blogName = useBlogName();
//outros códigos aqui
}
function useBlogName() {
/**
* ✅ Bom: está otimizado
*/
const name = useSelector((state) => state.blog.name);
return name;
}
Recapitulando:
Quanto mais específico seu seletor, melhor!
Isso evitará renders desnecessários nos seus componentes e os fará mais performáticos e resilientes a bugs.
Referências:
https://react-redux.js.org/api/hooks
https://redux.js.org/style-guide/#keep-state-minimal-and-derive-additional-values
Top comments (0)