从异步函数更新反冲状态

Update Recoil state from async function

我有一个应用程序可以在按下按钮时执行 API 操作。当动作结束时,我更新一个 Recoil 状态。但问题是,当我尝试更新状态时,我用更新后的新状态替换旧状态,并且在异步上下文中,我不知道如何在执行代码时获取当前状态。

const [tasks, setTasks] = useRecoilState(tasksState);

const handleAction = async (task: Task): Promise<void> => {
  try {
    // some async stuff here with an API

    // update the recoil state here
    // MY ISSUE HERE is that the "tasks" state is not the one at the moment where the code is executed after the API response, 
    // but at the moment where handleAction has been called...
    // So I can override the state with old values, previously updated from an other handleAction ended earlier.
    const newTasks = updateTasks(tasks, anOtherParameterFromApiResponse);
    setTasks(newTasks);
  } catch(error){
    console.log("error: ", error);
  }
}

你能告诉我如何处理这种模式并能够在我的异步操作结束时更新状态吗?

注意:我的状态是一个对象数组,我的 updateTasks() 函数是一个从这个数组更新对象的函数,所以我可以用这个计算数组更新状态。

预先感谢您给我宝贵的帮助!

我自己找到了解决办法:

我从我的任务 'atom' 创建了一个 'selector',并在自定义 'set' 方法中委托了新对象与对象数组状态的聚合。感谢参数中提供的 'get' 方法,我可以访问最新的对象数组状态。

selectors.ts :

/**
 * Allow to update the tasksState by passing in parameter the task to update
 * That way we can call this from an async context and updating value by agreagating to the eventual new ones
 */
export const taskUnitUpdaterSelector = selector<Task>({
  key: "taskUnitUpdaterSelector",
  get: () => {
    throw new Error("Not implemented !");
  },
  set: ({ get, set }, newTask: Docker) => {
    const tasks = get(tasksState);
    // remove from tasks list the new one updated to add it then
    const tasksCloneWithoutNewUpdatedOne = tasks.filter(
    (t) => !(t.name === newTask.name && t.server === newTask.server),
  );
  const newTasks = [...tasksCloneWithoutNewUpdatedOne , newTask];
  set(tasksState , newTasks);
});

component.ts

const taskUnitUpdater = useSetRecoilState(taskUnitUpdaterSelector);

const handleAction = async (task: Task): Promise<void> => {
  try {
    // some async stuff here with an API

    // the new tasks array is computed inside the selector set function to be able to access to up to date data !
    taskUnitUpdater(newTask );
  } catch(error){
    console.log("error: ", error);
  }
}