在history.listen上的useEffect中使用useState钩子



当我在useEffect中听到history的更改时,useState遇到了一些问题。

pathname改变时,setState被启动,但随后state被添加回来。

例如,我有一个flag组件,它收集通知组,但在pathname更改时,我希望从state中消除所有标志。

标志组件

const PageFlag = ({ history }: InterfaceProps) => {
const { contextData, dismissFlag, dismissAllFlags } = useContext(GlobalConsumer);
useEffect(() => {
history.listen(() => {
dismissAllFlags();
});
});
return (
<>
<FlagGroup onDismissed={dismissFlag}>
{contextData.flags.map((flag, index) => (
<Flag key={index} {...flag} />
))}
</FlagGroup>
</>
);
};

import { withRouter } from 'react-router-dom'使用历史道具

dismissAllFlags的状态和功能在createContext组件中显示为

const DefaultState: InterfaceState = {
otherStateExample: false,
flags: []
};
export const GlobalConsumer = createContext({
contextData: DefaultState,
addFlag: (flagData: any) => {},
dismissFlag: () => {},
dismissAllFlags: () => {}
});
export const GlobalProvider = ({ children }: InterfaceProps) => {
const [state, setState] = useState<InterfaceState>({
...DefaultState
});
return (
<GlobalConsumer.Provider
value={{
contextData: state,
addFlag: (flagData: any) => {
setState({ ...state, flags: [flagData].concat(state.flags) });
},
dismissFlag: () => {
setState({ ...state, flags: state.flags.slice(1) });
},
dismissAllFlags: () => {
setState({ ...state, flags: [] });
}
}}
>
{children}
</GlobalConsumer.Provider>
);
};

出现的问题是,在pathname更改时,dismissAllFlags使用setStateflags设置为[],但随后使用flags将先前的状态添加回来。

如何删除所有flags,但记住其他items的当前state

useEffect()上缺少第二个输入参数,这将导致侦听器在每次渲染时都被读取。

它应该是这样的,注意你也不应该需要内部功能。

useEffect(() => {
history.listen(dismissAllFlags)
}, []);

我们这样使用它:

const [isOpen, setIsOpen] = useState(false);
useEffect(() => {
history.listen(() => setIsOpen(false));
}, [history]);

如果我理解你的要求:

您希望将标志设置为空数组,而不必使用当前正在执行{...state, flags: []}的排列方法添加以前的值。

好吧,使用useState是不可能做到这一点的,对于嵌套状态对象应该小心,因为对于较大的对象,克隆可能会变得昂贵也许这就是你在这里试图避免的

即使你切换到useReducer,你最终仍然会支持该州的传播。

也许您应该将标志作为自己的状态const [flags, setFlags] = useState([]),或者查看不可变的助手。

此外,试着尊重react-hooks/exhaustive-deps其他妻子有趣的事情可能会开始发生。如果没有deps,那么至少给你的钩子一个空数组,以确保它执行一次。

最新更新