byte-fe / intern-study

实习生互助学习
MIT License
33 stars 6 forks source link

[第四期] Rethink react + state manage #27

Open leecade opened 5 years ago

leecade commented 5 years ago

背景

  1. 数年生产环境实践, redux 体系逐渐退出历史舞台, 对于 react 应用来说是时候反思更佳的状态管理实践了

  2. react 团队近期推动创新了很多新的 patterns, 从 Render Props / HOCnew Context / Hooks

  3. 团队技术积累重心放在 react 方向

希望同学们持续学习, 理解社区技术选型背后的逻辑, 拥抱新的变革

需求

兼容并包思考大中小型项目都能复用的状态管理架构理想情况下应该怎样, 权衡之下的分层策略, RN / SSR / 低配浏览器等平台环境下如何兼顾

简单考虑如下:

  1. 舍弃 store 概念, 复活 model 更贴切点, 我们定义一个 model 为:
import Model from 'react-model'

export default Model({
  state: {
    count: 0
  },
  actions: {
    increase: async (state, actions, payload) => {count: payload || state.count++}
  },
  middlewates: []
})

需要暴露出的核心 api 非常少, 就一个 Model

  1. 采用文件 import 形式表达导入关联关系, 文件结构组织上会很灵活, 关联分析的心智负担大大减少, 我们设计实例化后的 Model 接口签名为:
const {Provider, connect, actions, subscribe, unsubscribe, getState, useState, useAction} from 'models/modelA.js'

简单起见, 我们这期作业只思考 Provider / connect 的实现, 使用方式如下:

const {Provider, connect, actions} from 'models/modelA.js'

@connect(({ count }) => ({ count }))
class Page extends Component {
  render() {
    <div onClick={e => actions.increase(10)}>{this.props.count}</div>
  }
}

const Root = () => {
  <Provider>
     <Page />
  </Provider>
}

这里沿用了 redux 的范式, Provider 包裹根节点, connect 连接 view 和注入 model state 到 this.props

知识点和实现原理

更多思考

赶紧学习 Hooks, view 绑定的最终形态应该如下, 有兴趣的同学也可以思考下列实现:

import { useState, useAction } from 'models/modelA.js'

function Page() {
  const count = useState(state => state.count)
  const add = useAction(actions => actions.increase)
  return (
    <div onClick={e => actions.increase(10)}>{this.props.count}</div>
  )
}