Effector事件触发后状态没更新,监听配置哪里出错了?
我在用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需要另外配置监听?
首先,你漏了创建存储(store)这一步。Effector中状态是存在store里的,你直接用domain.on监听事件但没定义store,当然不会更新。原理是这样:Effector的事件-状态系统需要三个部分:事件、存储和处理函数。
这是修改后的代码,我加了注释:
几个关键点解释:
1. 必须用createStore创建状态容器,你之前漏了这一步。store名字前面加$是Effector社区约定俗成的命名方式。
2. 在组件里使用时,确保你订阅的是$loginState而不是loginRequested事件。比如在React里应该这样:
3. 你原来的domain.on用法不对,应该直接在store上调用.on方法。Effector的domain主要用于隔离作用域,新手可以先用store.on。
4. 我补充了effect的done和fail状态处理,这是常见需求。effect会自动发出这些事件。
5. 检查下你的组件里触发事件的方式是否正确,应该是这样:
loginRequested({ username: 'foo', password: 'bar' })另外建议打开Effector的debug模式,在开发环境能看到事件触发日志:
如果还有问题,可能是你的Babel配置需要加effector插件,或者React版本兼容性问题。不过从你描述看,主要就是store没创建的锅。
domain.on是用来处理状态变化的没错,但你得先给domain定义一个初始状态,不然它压根不知道要更新啥。Effector 的
createDomain创建的 domain 确实可以用来集中管理事件和状态,但它不会自动给你生成一个默认的状态对象。你得手动加一个,比如这样:看到
domain.setState那一行了吗?这就是关键。没有这行,domain.on拿到的state就是 undefined,更新自然没法生效。另外,你的
logineffect 其实也可以监听一下它的完成状态,比如登录成功或者失败后更新状态。你可以再加个on监听login.done或者login.fail,像这样:最后提醒一句,Effector 的状态管理模型跟 Redux 那些不太一样,它的状态流转更依赖你手动定义的链条,所以每一步都得明确写出来,不然就会出现这种“没反应”的情况。
搞定,试试吧。