Effector事件触发后状态没更新,监听配置哪里出错了?

UX-传志 阅读 3

我在用Effector处理用户登录状态时遇到问题,按文档写的事件监听就是不生效。代码里创建了登录事件和状态,用on方法关联了事件和状态更新函数,但实际触发事件后状态还是保持初始值,控制台也没报错。

这是我的代码片段:


import { createEvent, createEffect, createDomain } from 'effector';

const domain = createDomain();
export const loginRequested = domain.event();
export const login = createEffect(({ username, password }) => 
  fetch('/api/login', { body: { username, password } })
);

domain.on(loginRequested, (state, payload) => ({
  ...state,
  isLoading: true
}));

然后在组件里这样触发:

用useStore订阅到的isLoading始终是false,触发loginRequested事件后连控制台日志都没打印。是不是事件和状态的绑定姿势不对?或者Effect需要另外配置监听?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
极客树珂
你这个问题出在状态管理的根上,简单说就是缺了个初始状态。domain.on 是用来处理状态变化的没错,但你得先给 domain 定义一个初始状态,不然它压根不知道要更新啥。

Effector 的 createDomain 创建的 domain 确实可以用来集中管理事件和状态,但它不会自动给你生成一个默认的状态对象。你得手动加一个,比如这样:


import { createEvent, createEffect, createDomain } from 'effector';

const domain = createDomain();
// 定义初始状态
domain.setState({ isLoading: false });

export const loginRequested = domain.event();
export const login = createEffect(({ username, password }) =>
fetch('/api/login', { body: { username, password } })
);

domain.on(loginRequested, (state, payload) => ({
...state,
isLoading: true
}));


看到 domain.setState 那一行了吗?这就是关键。没有这行,domain.on 拿到的 state 就是 undefined,更新自然没法生效。

另外,你的 login effect 其实也可以监听一下它的完成状态,比如登录成功或者失败后更新状态。你可以再加个 on 监听 login.done 或者 login.fail,像这样:


domain.on(login.done, (state, { result }) => ({
...state,
isLoading: false,
isLoggedIn: true,
user: result
}));

domain.on(login.fail, (state, { error }) => ({
...state,
isLoading: false,
error: error.message
}));


最后提醒一句,Effector 的状态管理模型跟 Redux 那些不太一样,它的状态流转更依赖你手动定义的链条,所以每一步都得明确写出来,不然就会出现这种“没反应”的情况。

搞定,试试吧。
点赞
2026-02-19 12:09