首页
/ 在Effector中优雅地拆分Effect结果到不同Store

在Effector中优雅地拆分Effect结果到不同Store

2025-06-11 13:06:22作者:尤辰城Agatha

在Effector状态管理库的实际应用中,我们经常会遇到需要将一个Effect返回的结果拆分到多个Store中的场景。本文将探讨几种实现方式及其适用情况。

基础场景分析

假设我们有一个获取用户信息的Effect,它返回一个包含用户基本信息和用户偏好的复合对象:

const fetchUserInfo = createEffect(() => {
  return {
    user: { id: 1 },
    userPreferences: { darkMode: true },
  };
});

我们需要将这些数据分别存储到两个不同的Store中:$user$userPreferences

方案一:使用多个sample操作

最直接的方式是使用多个sample操作:

sample({
  clock: fetchUserInfo.doneData,
  fn: ({ user }) => user,
  target: $user,
});

sample({
  clock: fetchUserInfo.doneData,
  fn: ({ userPreferences }) => userPreferences,
  target: $userPreferences,
});

优点

  • 代码直观,易于理解
  • 不需要额外依赖
  • 类型推断良好

缺点

  • 当需要拆分的字段较多时,代码会显得重复

方案二:使用split操作

Effector提供了split操作符,可以根据条件将数据分流到不同的事件:

split({
  source: fetchUserInfo.doneData,
  match: {
    user: ({ user }) => !!user,
    userPreferences: ({ userPreferences }) => !!userPreferences
  },
  cases: {
    user: setUser,
    userPreferences: setUserPreferences,
  },
});

优点

  • 逻辑集中在一处
  • 适合复杂的分流条件

缺点

  • 需要预先定义事件处理器
  • 代码量不一定减少
  • 对于简单场景可能增加认知负担

方案三:自定义辅助函数

对于项目中的高频场景,可以创建自定义辅助函数:

function splitToStores(source, mappings) {
  Object.entries(mappings).forEach(([key, store]) => {
    sample({
      clock: source,
      fn: (data) => data[key],
      target: store,
    });
  });
}

// 使用方式
splitToStores(fetchUserInfo.doneData, {
  user: $user,
  userPreferences: $userPreferences
});

优点

  • 代码高度复用
  • 使用简洁
  • 可根据项目需求定制

缺点

  • 需要额外维护辅助函数
  • 类型支持可能受限

最佳实践建议

  1. 简单场景:直接使用多个sample操作最为合适,代码清晰且易于维护。

  2. 复杂分流:当需要根据复杂条件分流时,考虑使用split操作符。

  3. 高频使用:如果在项目中频繁遇到此类需求,可以创建自定义辅助函数来提高开发效率。

  4. 类型安全:在TypeScript项目中,优先选择类型支持良好的方案,通常多个sample操作能提供最好的类型推断。

总结

Effector提供了灵活的方式来处理Effect结果的拆分需求。开发者应根据具体场景选择最适合的方案,在代码简洁性、可读性和类型安全之间取得平衡。对于大多数情况,使用多个sample操作是最为推荐的做法,它既保持了代码的清晰度,又能获得良好的类型支持。

登录后查看全文
热门项目推荐
相关项目推荐