Effector 中如何正确处理异步事件的 loading 状态?

a'ゞ志鸽 阅读 19

我在用 Effector 做一个请求用户数据的功能,想在请求期间显示 loading,但发现状态总是同步更新,没法反映真实加载过程。我试过在 createEvent() 里直接 set true/false,但好像时机不对。

这是我的代码:

const fetchUser = createEvent();
const $loading = createStore(false);
const $user = createStore(null);

$loading.on(fetchUser, () => true);

sample({
  clock: fetchUser,
  target: createEffect(async (userId) => {
    const res = await api.getUser(userId);
    $user.setState(res);
    $loading.setState(false); // 这样写好像不规范?
  })
});

这样写会导致什么问题?应该怎么正确管理 loading 状态?

我来解答 赞 1 收藏
二维码
手机扫码查看
2 条解答
法霞 Dev
你的问题在于手动管理 loading 状态太土了,Effector 原生支持这个功能。

问题所在:在 effect 内部手动 setState 确实不规范,而且你只处理了成功的情况,失败时 loading 永远卡住。

正确做法:直接用 effect 的 .pending 属性。

const fetchUser = createEvent();

// 用 createEffect 替代手动 sample 到 effect
const fetchUserFx = createEffect({
handler: async (userId) => {
const res = await api.getUser(userId);
return res; // 记得 return,别在 effect 内部更新 store
}
});

// effect 自带 .pending 状态,直接派生 store
const $loading = fetchUserFx.pending;
const $user = createStore(null).on(fetchUserFx.done, (_, { result }) => result);

// 触发
sample({
clock: fetchUser,
target: fetchUserFx
});


就三步:
1. 用 createEffect 创建异步任务,它自带 pending/done/fail 状态
2. $loading = fetchUserFx.pending 直接派生 loading 状态,Effector 会自动在 effect 开始时设为 true,完成/失败时设为 false
3. 用 .on(fetchUserFx.done, ...) 处理成功结果,别在 effect 内部改 store

如果你还需要处理错误状态:
const $error = createStore(null).on(fetchUserFx.failData, (_, err) => err);


这样 loading、data、error 三种状态全搞定,而且是响应式的,effect 内部不用写任何 setState。
点赞
2026-03-18 18:25
FSD-艳鑫
effect.pending 代替手动创建的 $loading,Effector 的 effect 本身就内置了 pending 状态,会自动处理成功/失败的情况。

正确的写法:

const fetchUser = createEffect({
handler: async (userId) => {
const res = await api.getUser(userId); return res;
}
});

const $loading = fetchUser.pending; // 直接用 pending 状态
const $user = createStore(null);

$user.on(fetchUser.done, (_, { result }) => result);


你原来写法的最大问题:如果 effect 抛异常或请求失败,loading 永远卡在 true 状态。用 effect.pending 的话,无论是 done 还是 fail 都会自动重置,不用手动管。
点赞
2026-03-18 12:05