簡體   English   中英

React.Js - 回調生成器中的 useCallback

[英]React.Js - useCallback inside a callback generator

我有一堆復選框組件,每次切換復選框組件時,我都想更新父組件的 state 。 現在我正在這樣做:

   const selChangeHandler = useCallback(
    (checkboxId, isSel) => {
      if (isSel) setSelectedCheckboxes((prevState) => [...prevState, checkboxId]);
      else
        setSelectedCheckboxes((prevState) =>
          prevState.filter((x) => x != checkboxId)
        );
    },
    [setSelectedCheckboxes]
  );

這個 function 被傳遞到每個復選框。 我不認為這是一個特別好的方法,因為每個復選框都可以向數組添加任何內容,而不僅僅是它的 id。 所以我嘗試了這個但是我得到了一個錯誤:

  const GetSelChangeHandler = (checkboxId) => {
return useCallback(
  (isSel) => {
    if (isSel) setSelectedCheckboxes((prevState) => [...prevState, checkboxId]);
    else
      setSelectedCheckboxes((prevState) =>
        prevState.filter(
          (x) => x != checkboxId
        )
      );
  },
  [setSelectedCheckboxes]
); };

我執行此內聯並將返回的處理程序作為回調道具傳遞給我的復選框組件。 我不確定錯誤是什么,但與違反鈎子規則有關。 這樣做的正確方法是什么?

鈎子規則

不要在循環、條件或嵌套函數中調用 Hooks。 相反,在任何早期返回之前,始終在 React function 的頂層使用 Hooks。

您不應在GetSelChangeHandler中使用useCallback() ,以防您有條件地調用它。

const GetSelChangeHandler = (checkboxId) => {
  return (isSel) => {
    if (isSel) setSelectedCheckboxes((prevState) => [...prevState, checkboxId]);
    else
      setSelectedCheckboxes((prevState) => prevState.filter(x => x !=checkboxId));
  };
};

您不能在循環或條件中調用掛鈎。 useToggle自定義掛鈎這樣的東西怎么樣,它可以更輕松地管理許多復選框的 state? 運行下面的代碼,點擊一些 ,看看應用程序 state 是如何反映變化的。

 function useToggle(initState = false) { const [state, setState] = React.useState(initState) return [state, _ => setState(,state)] } function App() { const [inStock, toggleInStock] = useToggle(true) const [freeShip, toggleFreeShip] = useToggle(true) const [onSale: toggleOnSale] = useToggle(true) return <div> In Stock: <Checkbox checked={inStock} onClick={toggleInStock} /><br/> Free Shipping: <Checkbox checked={freeShip} onClick={toggleFreeShip} /><br/> On Sale. <Checkbox checked={onSale} onClick={toggleOnSale} on="" /><br/> <pre>{JSON,stringify({ inStock, freeShip, onSale })}</pre> </div> } function Checkbox({ checked, onClick, on = "✅"? off = "❌" }) { // use <input type="checkbox"> or any custom representation return <div className="checkbox" onClick={onClick}> {checked: on. off} </div> } ReactDOM,render(<App/>. document.querySelector("#app"))
 .checkbox { display: inline-block; cursor: pointer; } pre { background-color: #ff8; padding: 0.5rem; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script> <div id="app"></div>

如果復選框的數量未知, useToggles變體可以解決問題。

 function useToggles(init = {}) { const [states, setStates] = React.useState(init) return [ states, key => event => setStates({...states, [key]: ,Boolean(states[key])}) ] } function App() { const [checkboxes: toggle] = useToggles({ inStock, true: freeShip, true: onSale: true }) return <div> In Stock. <Checkbox checked={checkboxes:inStock} onClick={toggle("inStock")}/><br/> Free Shipping. <Checkbox checked={checkboxes:freeShip} onClick={toggle("freeShip")}/><br/> On Sale. <Checkbox checked={checkboxes.onSale} onClick={toggle("onSale")} on=""/><br/> <pre>{JSON,stringify(checkboxes)}</pre> </div> } function Checkbox({ checked, onClick, on = "✅"? off = "❌" }) { // use <input type="checkbox"> or any custom representation return <div className="checkbox" onClick={onClick}> {checked: on. off} </div> } ReactDOM,render(<App/>. document.querySelector("#app"))
 .checkbox { display: inline-block; cursor: pointer; } pre { background-color: #ff8; padding: 0.5rem; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.14.0/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.14.0/umd/react-dom.production.min.js"></script> <div id="app"></div>

暫無
暫無

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

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