Reactjs 使用某些道具触发useEffect()React挂钩,但在效果中引用其他道具
我有一个React用例,其中一个组件获得一个向下传递的Reactjs 使用某些道具触发useEffect()React挂钩,但在效果中引用其他道具,reactjs,react-hooks,Reactjs,React Hooks,我有一个React用例,其中一个组件获得一个向下传递的类别属性,并且还有一个本地状态值限制。我想要的行为是: 当选择类别时,如果当前高于10,则限制将重置为10 当类别被清除时,如果限制当前低于50,则将其重置为50 当类别保持不变时,用户可以选择所需的任何限制 我在效果挂钩中设置了此行为,如下图所示(更完整的示例): 使用ref跟踪上一个类别如何?它们相当于功能内组件 这样,您可以进行比较,并且仅在类别发生更改时运行效果代码,例如 const prevCat = useRef(null); u
类别
属性,并且还有一个本地状态值限制
。我想要的行为是:
类别
时,如果当前高于10,则限制将重置为10
类别
被清除时,如果限制
当前低于50,则将其重置为50类别
保持不变时,用户可以选择所需的任何限制
使用
ref
跟踪上一个类别如何?它们相当于功能内组件
这样,您可以进行比较,并且仅在类别发生更改时运行效果代码,例如
const prevCat = useRef(null);
useEffect(() => {
if (prevCat.current === category) return;
prevCat.current = category;
...
}, [category, limit]);
切换到管理限制
和类别
,并将两者传递到组件,而不是使用本地状态。这样,仅当其中一个值更改(或两者都更改)时才会渲染组件
const initialState={
类别:正确,
限额:10
};
功能减速机(状态、动作){
开关(动作类型){
案例“切换类别”:
如果(状态类别){
返回{category:false,limit:Math.min(50,state.limit)};
}
否则{
返回{category:true,limit:Math.max(10,state.limit)};
}
案例“设置限制”:
返回{…状态,限制:action.limit};
违约:
抛出新错误();
}
}
函数App(){
const[state,dispatch]=useReducer(reducer,initialState);
//React保证分派函数标识是稳定的,并且在重新渲染时不会更改。
//这就是为什么从useEffect或useCallback依赖项列表中省略是安全的。
const-toggleCategory=useCallback(()=>dispatch({type:'toggleCategory'}));
const setLimit=useCallback(limit=>dispatch({type:'setLimit',limit}));
返回(
切换类别
);
}
函数列表({category,limit,setLimit}){
返回(
setLimit(例如target.value)}>
{[5,10,25,50,100].map(d=>(
{d}
))}
类别为{类别?“开”:“关”}
将显示{limit}项
);
}
您可以使用setter的功能版本:
useEffect(() => {
setLimit((currentLimit) => {
if (category && currentLimit > 10) {
return 10;
} else if (!category && currentLimit < 50) {
return 50;
} else return currentLimit;
});
}, [category]);
useffect(()=>{
设置限制((当前限制)=>{
如果(类别和当前限制>10){
返回10;
}如果(!类别和当前限制<50),则为else{
返回50;
}否则返回电流限制;
});
},[类别];
const prevCat = useRef(null);
useEffect(() => {
if (prevCat.current === category) return;
prevCat.current = category;
...
}, [category, limit]);
const initialState = {
category: true,
limit: 10
};
function reducer(state, action) {
switch (action.type) {
case 'toggleCategory':
if (state.category) {
return {category: false, limit: Math.min(50, state.limit)};
}
else {
return {category: true, limit: Math.max(10, state.limit)};
}
case 'setLimit':
return {...state, limit: action.limit};
default:
throw new Error();
}
}
function App() {
const [state, dispatch] = useReducer(reducer, initialState);
// React guarantees that dispatch function identity is stable and won’t change on re-renders.
// This is why it’s safe to omit from the useEffect or useCallback dependency list.
const toggleCategory = useCallback(() => dispatch({type: 'toggleCategory'}));
const setLimit = useCallback(limit => dispatch({type: 'setLimit', limit}));
return (
<div className="App">
<button onClick={toggleCategory}>Toggle category</button>
<List {...state} setLimit={setLimit} />
</div>
);
}
function List({ category, limit, setLimit }) {
return (
<div>
<select value={limit} onChange={e => setLimit(e.target.value)}>
{[5, 10, 25, 50, 100].map(d => (
<option key={d}>{d}</option>
))}
</select>
<div>Category is {category ? "on" : "off"}</div>
<div>Would show {limit} items</div>
</div>
);
}
useEffect(() => {
setLimit((currentLimit) => {
if (category && currentLimit > 10) {
return 10;
} else if (!category && currentLimit < 50) {
return 50;
} else return currentLimit;
});
}, [category]);