Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

基于 region-core api,实现对于共享的单个加载数据的控制 #2

Closed
dancerphil opened this issue May 21, 2019 · 1 comment

Comments

@dancerphil
Copy link

dancerphil commented May 21, 2019

Prop 架构

在 region-core 第一次在组内介绍之后,@otakustay 问了我一个问题,他问你觉得 load(key, ...) 这个 key 是必须的吗?

当时,我认为是的,而且是必须的。相比于 mapStateToProps 内经常显得非常繁复的 selector,一个 key 是一种非常好的简略。

在使用 region-core 开发的过程中,我也不断的反思这个答案,从学术的角度,redux action 有其学术支撑。而这个在 region-core 中存在的 keyredux 的延伸,这看起来没有问题。但这个 key 确实是可以省去的。

暂时不管这样好不好,首先给出实现,我把这个新的对象取名为 Prop

Prop 使用和 Region 非常类似的原理,是 Region 的简化。而原先一个 region 内有多个通过 key 相互区别的 prop,现在 prop 可以单独进行管理:

const prop = new Prop({
  ...
})

// will get
const { set, loadBy, ..., useValue, useProps, getValue, getProps} = prop;

const App = ({id}) => {
  const result = prop.useValue();
  const { loading, error, fetchTime, result, results, id } = prop.useProps();
  // result always comes from results[id]
  useEffect(
    () => {
      /* 1. switch id
       * 2. load, set loading = true
       * 3. waiting for promise.resolve
       * 4. set loading = false & results[id] = nextResult
       */
      prop.loadBy(fetch)({id});
    },
    [id]
  );
  if (loading) {
    return 'loading...';
  }
  return <div>{results}</div>;
};

Prop 架构中不能实现的部分

这些变化中,会变差的部分如,框架无法帮你进行 loading, fetchTime, error 的计算

const { loading, fetchTime, error } = region.useProps(['a', 'b']);

// 需要转变为
const { loading: loadingA, fetchTime: fetchTimeA, error: errorA } = propA.useProps();
const { loading: loadingB, fetchTime: fetchTimeB, error: errorB } = propB.useProps();
const loading = loadingA || loadingB;
const fetchTime = min(fetchTimeA, fetchTimeB);
const error = [errorA?.message, errorB?.message].join(', ');

如果是 class componentconnect 带来的嵌套更长了,并且会丢失 useProps 里几乎所有的信息,基本上这个接口不再会有(这也是之前 key 不能省略的一个思想局限):

region.connect(['a', 'b', 'c'])(Component);

// 需要转变为
const enhance = compose(
  propA.connect('a'), // it must be a name or it can not be connected
  propB.connect('b'),
  propC.connect('c'),
);

其他的部分没有变得更差。

Prop 带来的好处

它的好处也比较显然,省去了 key 之后,开发者可以以更小的维度组织数据,他也可以准确的即插即用,丝毫不关心其他的 prop 对自己的影响(在 region 中如 loading 这类你希望它们互相影响的部分, 在 prop 中需要开发者自己定义影响的过程)

同时,它带来了重构友好,思奇在 review 的时候,觉得这个 key 作为一个字符串不是很好追踪,在较大的,且注重重构能力的应用中,可能需要把 keys 抽出来(类似 redux actions 一样)。如果要这么做,key 的命名会是一个新的约定,比如:

const { user } = region.useProps(USER);
const { user } = region.useProps($user);
const { user } = region.useProps(_user);
const { user } = region.useProps(userKey);

省去 key 自然就解决了这个问题。

同时,会保证开发者在 regionprop 之间相互切换是快的,在 propcontext 之间相互切换也是快的,这会使开发者拥有从小到大一系列数据管理选择:

  • 组件内单个数据:useState

  • 组件内单个加载数据:useFetch

  • 共享的单个数据:useContext ,参见 yesmeck/react-context-ioContext.write reactjs/rfcs#89

  • 共享的单个加载数据:prop.useProps

  • 共享的多个相互影响的加载数据:region.useProps

在多个数据管理方案之间迁移

这个 part 解答以下问题:

是否需要在一个项目引入所有的方案?如何在不同的方案间迁移?什么时候需要迁移?提供什么接口来迁移?成本多高?

现在在内部使用 region 的经验,可能 prop 可以满足大部分情况。如果要考虑在怎样的维度上拆分 region,极端一些的就是说任何情况都拆,就变成了 prop

@dancerphil dancerphil changed the title 基于 region-core 的技术,实现对于单 entity 的控制 基于 region-core api,实现对于单个共享可加载数据的控制 May 21, 2019
@dancerphil dancerphil changed the title 基于 region-core api,实现对于单个共享可加载数据的控制 基于 region-core api,实现对于共享的单个加载数据的控制 May 21, 2019
@dancerphil dancerphil reopened this May 23, 2019
@dancerphil
Copy link
Author

重命名 Entity => Prop ,由于 Prop 处理 Entity normalize 的问题,不再强调这方面的功能。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant