如何防止重新选择重新渲染?

我今天正在尝试reselect中间件并防止不必要的重新渲染。


这是我的 reducer.js:


const INITIAL_STATE = {

  dogs: 100,

  cats: 12312302384

};


const pets = (state = INITIAL_STATE, action) => {

  switch (action.type) {

    case "CHANGE_DOGS":

      return {

        ...state, dogs: state.dogs + 1

      };

    case "CHANGE_CATS":

      return {

        ...state, cats: state.cats + 1

      };

    default:

      return { ...state };

  }

};


export default pets;

这是我的 main.js:


import React from "react";

import { createSelector } from "reselect";

import { useSelector, useDispatch } from "react-redux";


function ReduxDeneme(props) {

  // Selectors - Classic style - NON Memoized!

//   const dogsData = useSelector(state => state.pets.dogs);

//   const catsData = useSelector(state => state.pets.cats);


  //                          Dogs rendering..  --> First opening..

  // 10:11:28.070 index.js:18 CATS rendering.. --> First opening..

  // 10:11:29.703 index.js:13 Dogs rendering.. --> Press "ChangeDogs" button.

  // 10:11:29.703 index.js:18 CATS rendering..  --> Press "ChangeDogs" button.

  // 10:11:33.143 index.js:13 Dogs rendering.. --> Press "ChangeCats" button.

  // 10:11:33.143 index.js:18 CATS rendering..  --> Press "ChangeCats" button.


  // Selectors - Memoized version RESELECT middleware'i ile..

  const dogsDataMemo = createSelector(

    state => state.pets.dogs,

    dogs => dogs

  );

  const catsDataMemo = createSelector(

    state => state.pets.cats,

    cats => cats

  );


  const dogsData = useSelector(dogsDataMemo)

  const catsData = useSelector(catsDataMemo)



  // Components

  const Dogs = ({ dogsData }) => {

    console.log("Dogs rendering..");

    return <h1>{dogsData}</h1>;

  };


  const Cats = ({ catsData }) => {

    console.log("Cats rendering..");

    return <h1>{catsData}</h1>;

  );

}


export default ReduxDeneme;

1. 场景:我使用了经典的、非记忆的样式选择器。控制台上有6次console.log。(第一次打开2次-正常-,点击“换狗”按钮2次,点击“换猫”按钮2次)。这意味着发生了 6 次重新渲染。

2. 场景:我使用reselect了中间件来防止不必要的重新渲染。但是,它不起作用或者我误解了reselect.

有人可以解释正确的方法或我在哪里做错了吗?


森林海
浏览 172回答 2
2回答

HUX布斯

您正在组件内定义选择器。你应该在外面做(例如你的减速器附近的某个地方)。目前,您正在每次渲染后重新创建选择器。这是一个更好的方法:// inside reducer.js&nbsp; export const petsSel = state => state.pets;&nbsp; export const dogsDataMemo = createSelector(&nbsp; &nbsp; petsSel,&nbsp; &nbsp; pets => pets.dogs&nbsp; );&nbsp; export const catsDataMemo = createSelector(&nbsp; &nbsp; petsSel,&nbsp; &nbsp; pets => pets.cats&nbsp; );根据您的代码添加了带有工作示例的代码框:https ://codesandbox.io/s/delicate-snowflake-5ssrw为了实现你想要的,你还需要使用 React.memo ( https://reactjs.org/docs/react-api.html#reactmemo ):const Dogs = React.memo(({ dogsData }) => {&nbsp; console.log("Dogs rendering..");&nbsp; return <h1>{dogsData}</h1>;});

PIPIONE

首先,我非常感谢@tudor 的努力。他说的都是对的。但是,我想证明 Reselect 有效。场景 1 - 非记忆import React, { memo } from "react";import { useSelector, useDispatch } from "react-redux";// import { catsDataMemo, dogsDataMemo } from "./selectors";// Componentsconst Dogs = memo(({ dogsData }) => {&nbsp; console.log("Dogs rendering..");&nbsp; return <h1>{dogsData}</h1>;});const Cats = memo(({ catsData }) => {&nbsp; console.log("Cats rendering..");&nbsp; return <h1>{catsData}</h1>;});function ReduxDeneme() {&nbsp; // Standart useSelector without MEMOIZED&nbsp; const dogsData = useSelector(&nbsp; &nbsp; state => state.pets.dogs,&nbsp; &nbsp; console.log("dogsData Selector çalıştı.")&nbsp; );&nbsp; const catsData = useSelector(&nbsp; &nbsp; state => state.pets.cats,&nbsp; &nbsp; console.log("catsData Selector çalıştı.")&nbsp; );&nbsp; // Actions&nbsp; const dispatch = useDispatch();&nbsp; const changeDogs = () => dispatch({ type: "CHANGE_DOGS" });&nbsp; const changeCats = () => dispatch({ type: "CHANGE_CATS" });&nbsp; const noChangeCats = () =>&nbsp; &nbsp; dispatch({ type: "NO_CHANGE_CATS", payload: catsData });&nbsp; return (&nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; <Dogs dogsData={dogsData} />&nbsp; &nbsp; &nbsp; <Cats catsData={catsData} />&nbsp; &nbsp; &nbsp; <button onClick={changeDogs}>Change Dogs</button>&nbsp; &nbsp; &nbsp; <button onClick={changeCats}>Change CATS</button>&nbsp; &nbsp; &nbsp; <button onClick={noChangeCats}>No Change</button>&nbsp; &nbsp; </div>&nbsp; );}export default memo(ReduxDeneme);当心!当您单击“更改狗”按钮时,控制台中的输出将是:dogsData Selector çalıştı.catsData Selector çalıştı.Dogs rendering..或者当您单击“更改猫”按钮时,输出将是:dogsData Selector çalıştı.catsData Selector çalıştı.Cats rendering..无论您按什么按钮,这两个 useSelectors 都将起作用,正如您从 console.log 中看到的那样场景 2 - 使用重新选择中间件进行记忆首先,正如@tudor.gergely 提到的,我们将记忆选择器分离到另一个文件中。小心点!您必须定义对象的正确路径。// selectors.jsimport { createSelector } from "reselect";export const dogsDataMemo = createSelector(&nbsp; state => state.pets.dogs, // BE CAREFULL while defining..&nbsp; dogs => {&nbsp; &nbsp; console.log("DogsDataMemo has worked.");&nbsp; &nbsp; return dogs;&nbsp; });export const catsDataMemo = createSelector(&nbsp; state => state.pets.cats, // BE CAREFULL while defining..&nbsp; cats => {&nbsp; &nbsp; console.log("CatsDataMemo has worked.");&nbsp; &nbsp; return cats;&nbsp; });然后,我们将这个文件导入到 main.js 文件中,并再次将 useSelector 与我们的记忆选择器一起使用:import React, { memo } from "react";import { useSelector, useDispatch } from "react-redux";import { catsDataMemo, dogsDataMemo } from "./selectors";// Componentsconst Dogs = memo(({ dogsData }) => {&nbsp; console.log("Dogs rendering..");&nbsp; return <h1>{dogsData}</h1>;});const Cats = memo(({ catsData }) => {&nbsp; console.log("Cats rendering..");&nbsp; return <h1>{catsData}</h1>;});function ReduxDeneme() {&nbsp; const dogsData = useSelector(dogsDataMemo);&nbsp; const catsData = useSelector(catsDataMemo);&nbsp; // Actions&nbsp; const dispatch = useDispatch();&nbsp; const changeDogs = () => dispatch({ type: "CHANGE_DOGS" });&nbsp; const changeCats = () => dispatch({ type: "CHANGE_CATS" });&nbsp; const noChangeCats = () =>&nbsp; &nbsp; dispatch({ type: "NO_CHANGE_CATS", payload: catsData });&nbsp; return (&nbsp; &nbsp; <div>&nbsp; &nbsp; &nbsp; <Dogs dogsData={dogsData} />&nbsp; &nbsp; &nbsp; <Cats catsData={catsData} />&nbsp; &nbsp; &nbsp; <button onClick={changeDogs}>Change Dogs</button>&nbsp; &nbsp; &nbsp; <button onClick={changeCats}>Change CATS</button>&nbsp; &nbsp; &nbsp; <button onClick={noChangeCats}>No Change</button>&nbsp; &nbsp; </div>&nbsp; );}export default memo(ReduxDeneme);和最终输出:单击“更改狗”按钮时:DogsDataMemo has worked.Dogs rendering单击“更改猫”按钮时:CatsDataMemo has worked.Cats rendering..
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript