reactjs 重用React钩子内的输入道具:为什么结果没有更新?

3lxsmp7m  于 2022-11-29  发布在  React
关注(0)|答案(1)|浏览(99)

ViewDispatcher组件中,我使用react-use库中的useList钩子获取输入属性initialItems并创建items变量。这有助于我使用update方法轻松地操作列表:

export const ViewDispatcher = ({ mode, loading, items: initialItems }) => {
  const [items, { update }] = useList(initialItems);
  console.log("[ViewDispatcher] Rendering", initialItems, items);

  switch (mode) {
    case "list":
      if (loading) {
        return null;
      }

      return <>{JSON.stringify(items)}</>;
    default:
      throw new Error("Unsupported view.");
  }
};

我面临的问题(pen here)是:**为什么我的items变量为空,而initialItems被正确填充?**我禁用了React strict模式以避免污染日志:
[视图调度程序]呈现[] []
[ViewDispatcher]呈现[对象,对象,对象,对象,对象,对象,对象,对象,对象,...] []
输入items来自View组件,该组件只是从

export const View = () => {
  const [{ loading, items }, setState] = useState({ loading: true, items: [] });

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/todos")
      .then((res) => res.json())
      .then((items) => {
        setState((prev) => ({ ...prev, loading: false, items }));
      });
  }, []);

  return <ViewDispatcher mode="list" loading={loading} items={items} />;
};
tvokkenx

tvokkenx1#

React会保存初始状态一次,并在下次渲染时忽略它,这样做的任何操作都将被忽略:

1.通过props更新初始状态:

function ViewDispatcher(items) {
  const [state, setState] = useState(items);
}

在第一次呈现时,ViewDispatcher从项中接收[],并因此设置initialState,在由属性更改引起的后续呈现时,来自items的新值将被忽略。

2.重新创建初始状态:

function ViewDispatcher() {
  const [state, setState] = useState(createInitialStateFn());
}

在第一次呈现时,状态由createInitialStateFn()初始化一次,在后续呈现时,将忽略从createInitialStateFn()返回的任何内容。

要解决此问题

您可以将useList提升到父组件,并使用useList库中的update函数更新状态,就像dot then块中的setState((prev) => ({ ...prev, loading: false, items }));一样。

您可能需要正确地重构状态:

父组件和子组件都保持items状态,很有可能可以将这两个状态合并为一个状态,否则,每次状态更改时,都必须使用setter同时更新这两个状态,以便保持它们同步。
而创建一个独立的加载状态特别是最适合你的情况我想:

const [loading, setLoading] = useState(true);

相关问题