从自定义钩子发出的状态更改即使添加到 useEffect 也不会导致重新渲染

rea*_*tor 7 reactjs react-hooks

我有一个自定义钩子,它保留了一个切换状态列表,虽然我看到内部状态与我的期望一致,但我想知道为什么一个监听这个钩子保持的状态变化的组件没有重新渲染在变化。代码如下

const useToggle = () => {
  const reducer = (state, action) => ({...state, ...action});
  const [toggled, dispatch] = useReducer(reducer, {});
  const setToggle = i => {
    let newVal;
    if (toggled[i] == null) {
      newVal = true;
    } else {
      newVal = !toggled[i];
    }
    dispatch({...toggled, [i]: newVal});
    console.log('updated toggled state ...', toggled);
  };
  return {toggled, setToggle};
};

const Boxes = () => {
  const {setToggle} = useToggle()
  return Array.from({length: 8}, el => null).map((el,i) => 
  <input type="checkbox" onClick={() => setToggle(i)}/>)
  }

function App() {
  const {toggled} = useToggle()
  const memoized = useMemo(() => toggled, [toggled])
  useEffect(() => {
    console.log('toggled state is >>>', toggled) // am not seeing this on console after changes to toggled
  }, [toggled])

  return (
    <div className="App">
      <Boxes />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

dan*_*die 8

那是因为你用了useToggle两次。

  1. 一旦在 App
  2. 中的另一个Boxes

当您在 中分派操作时Boxes,它会更新(未在其中检索)的toggled实例Boxes

想想你的自定义钩子,就像你如何使用useState. 当您使用 时useState,每个组件都有自己的状态。自定义钩子也是如此。

所以有几种方法可以解决这个问题。

  1. setTogglefrom传递AppBoxesvia prop-drilling
  2. 使用 Context API(或 Redux 或其他语句管理库setToggleApp组件中的实例向下传递 )

这是一个螺旋钻的例子。
你可以跟着
编辑so.answer.57130413

const Boxes = ({ setToggle }) => {
  // const { setToggle } = useToggle();
  return Array.from({ length: 8 }, el => null).map((el, i) => (
    <input key={i} type="checkbox" onClick={() => setToggle(i)} />
  ));
};

function App() {
  const { toggled, setToggle } = useToggle();

  useEffect(() => {
    console.log("toggled state is >>>", toggled); // am not seeing this on console after changes to toggled
  }, [toggled]);

  return (
    <div className="App">
      <Boxes setToggle={setToggle} />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

注意:我keyBoxes使用索引时添加了道具i(顺便说一下,这是一个不好的做法)

您可以看到它现在按您的预期工作。
演示

  • 您可以使用钩子来“共享逻辑”,而不是状态。您可以搜索“使用相同 Hook 的两个组件是否共享状态?” 不。自定义 Hooks 是一种在文档中重用状态逻辑的机制。这很难理解,但过了这么久我仍然明白 (3认同)