【问题标题】:How to update React state once useMutation is done?完成 useMutation 后如何更新 React 状态?
【发布时间】:2021-05-17 13:32:27
【问题描述】:

我使用 react-query 的 useMutation 钩子将用户添加到 api。有用。现在,我需要将新用户添加到处于我状态的用户数组中。

我知道我应该使用 useQuery 查询所有用户,然后在 useMutation 中使用 onSuccess 来修改缓存。但在某些情况下,我不会使用 useQuery 获取用户,因此我需要像使用普通承诺一样更新本地状态。

目前,我只是检查道具“成功”是否为真,如果是,我更新数组。但它只适用于第二次点击。为什么以及如何解决这个问题?

似乎 onAddUser() 内部的成功条件只有在第二次点击时才能达到。

export default function App() {
  const { updateUser } = userService();
  const { update, loading, error, data, success } = updateUser();
  const [users, setUsers] = useState(allUsers);

  const onAddUser = async () => {
    await update(newUser);
    if (success) {
      return setUsers((users) => [...users, data]);
    }
  };

  return (
    <>
      <div>
        {users.map((user) => (
          <div key={user.id}>
            {user.name} - {user.job}
          </div>
        ))}
      </div>
      {loading && <div>sending...</div>}
      {error && <div>error</div>}
      <button onClick={() => onAddUser()}>add user</button>
    </>
  );
}

这里也是一个沙盒:https://codesandbox.io/s/usemutation-test-co7e9?file=/src/App.tsx:283-995

【问题讨论】:

  • 我认为这是因为查询的异步性质。当您在 onAddUser 中执行 update() 时,它会异步评估,因此只有下一次才会成功。尝试添加const update = await update(newUser),并在下一行计算update.success

标签: reactjs react-query


【解决方案1】:

updateUser 返回的 success 属性(我假设这是 useMutation 返回的结果)只会在下一个渲染周期更新。即使您在那里有异步等待,函数仍将保留对它们关闭的任何内容的引用。这与 react-query 无关,这就是 react 的工作原理。

我建议使用突变函数的onSuccess 回调,或者使用mutateAsync 并检查结果,但如果使用mutateAsync,请记住手动捕获错误。你可以阅读mutateAsynchere,我会给你看一个mutate的例子:

const { mutate, loading } = useMutation(() => ...);
const onAddUser = () =>
    mutate(newUser, {
        onSuccess:  (newData) => setUsers((users) => [...users, data]);
    });
  };

另外,请不要违反钩子的规则。您只能从功能组件或其他钩子(=以use 开头的函数)调用钩子,但在您的代码盒中,您可以从updateUser 函数调用useMutation ...

【讨论】:

  • 谢谢!但是,我不喜欢在我的组件中使用 useMutation 或 useQuery,因为我更喜欢分离关注点。在我看来,api 问题应该在 api 服务中处理。这个钩子规则只是“行为准则”规则还是可能导致错误和崩溃的东西?我使用相同模式的 useQuery 和 useInfiniteQuery 并且从未遇到任何问题。
  • 是的,首选模式是将其抽象为自定义挂钩 - 只需将您的服务命名为 useUserService 就可以了。由于您的服务使用了钩子(useQuery、useMutation...),因此您不能在 react 组件和其他自定义钩子之外调用它。
猜你喜欢
  • 2017-01-01
  • 1970-01-01
  • 2021-06-18
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
  • 2017-03-22
  • 1970-01-01
  • 2020-07-28
相关资源
最近更新 更多