Easy Peasy 中如何正确监听 store 变化并触发副作用?

欧阳丽丽 阅读 14

我在用 Easy Peasy 做一个 React 项目,想在某个状态更新后自动执行一个副作用(比如发请求),但发现直接在组件里 useEffect 监听 store 状态好像没反应。

我试过这样写:useEffect(() => { fetchData(); }, [store.someValue]),但 someValue 更新后副作用没触发。是不是得用 Easy Peasy 提供的监听机制?

看到文档里有 onAction 和 thunk,但不太清楚具体怎么用。比如我想在 user.id 变更时重新拉取用户详情,该怎么写?

const store = createStore({
  user: {
    id: null,
    profile: {},
    setId: action((state, payload) => {
      state.id = payload;
    }),
    // 这里怎么加监听逻辑?
  }
});
我来解答 赞 4 收藏
二维码
手机扫码查看
1 条解答
爱学习的芹芹
我血泪教训告诉你,别在组件里用 useEffect 直接监听 Easy Peasy store 的状态,它根本不会触发重新渲染,因为 Easy Peasy 是基于 immer 的,内部状态变更不会触发 React 的 diff,你监听的 store.someValue 可能是个代理对象引用,永远不变。

要实现「状态变更后自动触发副作用」,正确姿势是用 thunk,别用 onAction(那个更适合日志、埋点这类通用逻辑,不适合业务副作用)。

你这个场景,应该这样写:

const store = createStore({
user: {
id: null,
profile: {},
setId: action((state, payload) => {
state.id = payload;
}),
fetchProfile: thunk(async (actions, payload, { getStoreState }) => {
const currentId = getStoreState().user.id;
if (!currentId) return;
const res = await fetch(/api/user/${currentId});
const data = await res.json();
actions.setProfile(data);
}),
setProfile: action((state, payload) => {
state.profile = payload;
})
}
});


然后在组件里这样用:

const { user, setUser } = useStoreState(state => ({ user: state.user }));
const { fetchProfile } = useStoreActions(actions => actions.user);

useEffect(() => {
if (user.id) {
fetchProfile();
}
}, [user.id, fetchProfile]);


注意!这里 useEffect 里监听的是 user.id,但这个 user 是你从 store 里用 useStoreState 选出来的,Easy Peasy 会把选中的字段做 shallow compare,变了就会触发 effect。

我当初就踩过坑,直接用 store.user.id 当依赖,结果依赖数组永远是同一个代理对象,effect 根本不跑。记住:监听必须用 useStoreState 提供的值,不能直接用 store 实例。

还有一种更骚的操作是用 onAction + thunk 组合,但容易死循环,不推荐:

const store = createStore({
user: { ... },
onAction: action((state, payload) => {
if (payload.type === 'user/setId') {
// 别在这直接发请求!会卡死!
// 正确做法是 dispatch 一个 thunk
store.dispatch.user.fetchProfile(); // 这里会报错!store 没定义
}
})
}, {
middleware: thunk.withExtraArgument(() => store) // 这种写法也容易崩
});


真要这么写得用 createStore 的第二个参数传 middleware,但太绕,容易把自己绕进去。还是前面那种在组件里用 useEffect + useStoreActions 最稳妥,清晰好调试,别图省事。
点赞 3
2026-02-25 09:17