2 回答
TA贡献1876条经验 获得超6个赞
您正在组件内定义选择器。你应该在外面做(例如你的减速器附近的某个地方)。
目前,您正在每次渲染后重新创建选择器。这是一个更好的方法:
// inside reducer.js
export const petsSel = state => state.pets;
export const dogsDataMemo = createSelector(
petsSel,
pets => pets.dogs
);
export const catsDataMemo = createSelector(
petsSel,
pets => pets.cats
);
根据您的代码添加了带有工作示例的代码框:https ://codesandbox.io/s/delicate-snowflake-5ssrw
为了实现你想要的,你还需要使用 React.memo ( https://reactjs.org/docs/react-api.html#reactmemo ):
const Dogs = React.memo(({ dogsData }) => {
console.log("Dogs rendering..");
return <h1>{dogsData}</h1>;
});
TA贡献1829条经验 获得超9个赞
首先,我非常感谢@tudor 的努力。他说的都是对的。
但是,我想证明 Reselect 有效。
场景 1 - 非记忆
import React, { memo } from "react";
import { useSelector, useDispatch } from "react-redux";
// import { catsDataMemo, dogsDataMemo } from "./selectors";
// Components
const Dogs = memo(({ dogsData }) => {
console.log("Dogs rendering..");
return <h1>{dogsData}</h1>;
});
const Cats = memo(({ catsData }) => {
console.log("Cats rendering..");
return <h1>{catsData}</h1>;
});
function ReduxDeneme() {
// Standart useSelector without MEMOIZED
const dogsData = useSelector(
state => state.pets.dogs,
console.log("dogsData Selector çalıştı.")
);
const catsData = useSelector(
state => state.pets.cats,
console.log("catsData Selector çalıştı.")
);
// Actions
const dispatch = useDispatch();
const changeDogs = () => dispatch({ type: "CHANGE_DOGS" });
const changeCats = () => dispatch({ type: "CHANGE_CATS" });
const noChangeCats = () =>
dispatch({ type: "NO_CHANGE_CATS", payload: catsData });
return (
<div>
<Dogs dogsData={dogsData} />
<Cats catsData={catsData} />
<button onClick={changeDogs}>Change Dogs</button>
<button onClick={changeCats}>Change CATS</button>
<button onClick={noChangeCats}>No Change</button>
</div>
);
}
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.js
import { createSelector } from "reselect";
export const dogsDataMemo = createSelector(
state => state.pets.dogs, // BE CAREFULL while defining..
dogs => {
console.log("DogsDataMemo has worked.");
return dogs;
}
);
export const catsDataMemo = createSelector(
state => state.pets.cats, // BE CAREFULL while defining..
cats => {
console.log("CatsDataMemo has worked.");
return cats;
}
);
然后,我们将这个文件导入到 main.js 文件中,并再次将 useSelector 与我们的记忆选择器一起使用:
import React, { memo } from "react";
import { useSelector, useDispatch } from "react-redux";
import { catsDataMemo, dogsDataMemo } from "./selectors";
// Components
const Dogs = memo(({ dogsData }) => {
console.log("Dogs rendering..");
return <h1>{dogsData}</h1>;
});
const Cats = memo(({ catsData }) => {
console.log("Cats rendering..");
return <h1>{catsData}</h1>;
});
function ReduxDeneme() {
const dogsData = useSelector(dogsDataMemo);
const catsData = useSelector(catsDataMemo);
// Actions
const dispatch = useDispatch();
const changeDogs = () => dispatch({ type: "CHANGE_DOGS" });
const changeCats = () => dispatch({ type: "CHANGE_CATS" });
const noChangeCats = () =>
dispatch({ type: "NO_CHANGE_CATS", payload: catsData });
return (
<div>
<Dogs dogsData={dogsData} />
<Cats catsData={catsData} />
<button onClick={changeDogs}>Change Dogs</button>
<button onClick={changeCats}>Change CATS</button>
<button onClick={noChangeCats}>No Change</button>
</div>
);
}
export default memo(ReduxDeneme);
和最终输出:
单击“更改狗”按钮时:
DogsDataMemo has worked.
Dogs rendering
单击“更改猫”按钮时:
CatsDataMemo has worked.
Cats rendering..
添加回答
举报
