2 回答

TA貢獻(xiàn)1876條經(jīng)驗(yàn) 獲得超6個贊
您正在組件內(nèi)定義選擇器。你應(yīng)該在外面做(例如你的減速器附近的某個地方)。
目前,您正在每次渲染后重新創(chuàng)建選擇器。這是一個更好的方法:
// 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
);
根據(jù)您的代碼添加了帶有工作示例的代碼框:https ://codesandbox.io/s/delicate-snowflake-5ssrw
為了實(shí)現(xiàn)你想要的,你還需要使用 React.memo ( https://reactjs.org/docs/react-api.html#reactmemo ):
const Dogs = React.memo(({ dogsData }) => {
console.log("Dogs rendering..");
return <h1>{dogsData}</h1>;
});

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超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);
當(dāng)心!當(dāng)您單擊“更改狗”按鈕時,控制臺中的輸出將是:
dogsData Selector ?al??t?.
catsData Selector ?al??t?.
Dogs rendering..
或者當(dāng)您單擊“更改貓”按鈕時,輸出將是:
dogsData Selector ?al??t?.
catsData Selector ?al??t?.
Cats rendering..
無論您按什么按鈕,這兩個 useSelectors 都將起作用,正如您從 console.log 中看到的那樣
場景 2 - 使用重新選擇中間件進(jìn)行記憶
首先,正如@tudor.gergely 提到的,我們將記憶選擇器分離到另一個文件中。
小心點(diǎn)!您必須定義對象的正確路徑。
// 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;
}
);
然后,我們將這個文件導(dǎo)入到 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..
添加回答
舉報(bào)