Recoil 请求的刷新之使用随机参数

官方文档有对请求如何刷新的操作指引,是基于 Recoil 本身的一些概念来完成的。

本质上,对于如下的异步状态:

export const todoQuery = selectorFamily<
  { title: string },
  { id: number }
>({
  key: "todo",
  get: ({ id }) => async ({ get }) => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
    const todos = res.json();
    return todos;
  },
});

因为 Recoil 状态是幂等的,只要入参 id 不变,输出也不会变,即,对于相同的 id 只首次会发起请求,后续都直接从缓存返回而不会直接发起请求。

如果想要强制刷新,需要增加一个入参,改变这个入参即可,比如增加一个 requestId

export const todoQuery = selectorFamily<
  { title: string },
-  { id: number }
+  { refreshId: number; id: number }
>({
  key: "todo",
-  get: ({ id }) => async ({ get }) => {
+  get: ({ refreshId, id }) => async ({ get }) => {
    const res = await fetch(`https://jsonplaceholder.typicode.com/todos/${id}`);
    const todos = res.json();
    return todos;
  },
});

刷新请求的地方:

export function TodoInfo({ id }: ITodoInfoProps) {
  const name = useRecoilValue(nameState);
  const [refreshId, setRefreshId] = useState(0);
  const todo = useRecoilValue(todoQuery({ refreshId: refreshId, id }));

  useEffect(() => {
    // 其他依赖变更后进行刷新
    setRefreshId(Math.random());
  }, [name]);

  return (
    <div>
      {todo.title}
      <button
        onClick={() => {
          // 点击按钮刷新
          setRefreshId(Math.random());
        }}
      >
        refresh
      </button>
    </div>
  );
}

无论是有其他依赖变更后需要刷新,还是手动点击按钮触发刷新,都可以通过更新新增的这个入参来达到刷新的目的。

相关资源