簡體   English   中英

在 history.listen 的 useEffect 中使用 useState 鈎子

[英]Using useState hook in useEffect on history.listen

在收聽useEffecthistory變化時,我在使用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的 state 和 function 在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設置為[]但隨后將先前的 state 與flags添加回來。

如何刪除所有flags但記住其他items的當前state

您缺少useEffect()上的第二個輸入參數,這將導致在每次渲染時都讀取偵聽器。

它應該看起來像這樣,注意你也不應該需要內部 function。

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

我們像這樣使用它:

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

如果我明白你的要求是這樣的:

您想將標志設置為空數組,而不必使用您當前正在執行的擴展方法添加先前的值{...state, flags: []}

好吧,使用useState是不可能的,您應該注意嵌套的 state 對象,因為使用較大的對象進行克隆可能會變得昂貴。 也許這就是你在這里試圖避免的

即使您切換到useReducer ,您最終仍會為 state 進行道具傳播。

也許您應該將標志作為自己的 state const [flags, setFlags] = useState([])或查看immutable-helper

此外,盡量尊重react-hooks/exhaustive-deps otherwives 有趣的事情可能會開始發生。 如果沒有部門,那么至少給你的鈎子一個空數組以確保它執行一次。

我嘗試使用您的代碼在 CodeSandbox 上重現您的問題。 但一切正常。

你可以在這里查看:

編輯居高臨下的kapitsa-l2j4i

可能出現的問題:

  • 可能是您在調用addFlag之后立即在某處調用dismissAllFlags 我在沙盒示例中添加了注釋行。 使用這一行,代碼就像您在問題中描述的那樣工作。
  • 另一個版本的依賴項。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM