最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 从工程实践来理解 React 中的 state 和 props

    正文概述 掘金(掘金泥石流)   2020-12-27   549

    前言

    有一两个月没写文章了, 最近一直在忙一些工作上的事情, 做了很多工程上的实践, 关于 React 应用研发框架这件事, 目前我和我的同事们也取得了一些有意思的成果, 估计 2021 年应该会围绕这些成果比较密集的发声, 希望能给 React 应用研发在工程实践上带来一些不一样的东西, 这篇文章要聊的关于 React 中 state 和 props 的思考也是我们实践成果中整理出来的理论一部分

    正文

    经过这几年大量优秀的同行们的不断实践, React 带来的 state 和 props 这两种概念已经不局限于仅仅是通过 React 来研发应用, 而是泛化成了一些工程实践上我们对前端应用中状态的讨论, 这些讨论围绕着什么是 state 又或者什么是 props, 在很多理论条件下, 我们都试图去严格区分两者, 并寻找其中的边界, 但在实际的实践中却做不到这一点.

    最典型的在于 redux 在早期的文档中提倡将应用的 state 统一设计, props 本身是从 root 向下传递的, 基于 redux 的单一 store 的理念, 所有的 state 都被抽象到 root 上层的 Provider, 这种方式其实就是通过统一应用的状态来消灭 props.

    如果你严格按照 react-redux 的设计来构建你的应用, 通过 connect 来代替 props 透传, 通过 selector 来代替从 props 计算 state 的过程, 那么从理论上看, props 是可以完全被 state 代替掉, 一个应用可以通过单一 store 实现状态的全局控制.

    这种思想其实也是 redux 作者在早期分享 redux 所提到的应用的时间旅行的理论基础. 试想下, 如果一个应用的 state 脱离了 store, 那么时间旅行也就行不通了.

    但越来越多的实践证明, 应用的 state 具有明显的演进特性, 根本无法在一开始就能被设计清楚

    事实上在接下来的几年, 围绕 redux 的争议也从未停止, 随着 redux 的实践越来越多, 社区开始接受现实, 且不说应用的时间旅行是否具有实际的工程价值, 单一 store 的问题却越来越多.

    • state 设计成本高, 单一 store 无法很好的维护 state 的增长
    • 对于部分 react 组件来说 local state 是必然存在的, 但 store 里的 state 又算什么?
    • 严格按照 connect selector 的方式非常反人类, react 全家桶导致状态管理陷入一种混乱

    直到 react hooks 发布, 内置的 useReducer, 从某种程度上给过往的实践和讨论划下了一个句号, 虽然官方并没有给出 hooks 在 state 管理上的官方指导, react-redux 也更新了 hooks api, 但我看来这可能标志这一个围绕 redux 进行 state 管理的时代的结束.

    让我们回到 state 和 props 本身, 从源头去看待他们

    state 翻译过来是状态, props 翻译过来是属性, 在大量实践中, 这两者其实经常存在一种转换关系, 当产品需求不断发生变更, state 传递给子组件, 变成 props, 子组件从 props 计算自身的 state 几乎已经成为 React 应用研发的常态, 但这种 state → props → state 的双向关系, 不仅仅带来的是数据流的混乱, 更容易引发循计算导致各种未知的 bug.

    但是如果我们尝试着建立一种边界, 给 state 和 props 加上一层理解呢?

    比如 internal state, external props.

    我们可以试着将 state 看成是一个组件内部的一部分, 之前社区吐槽 hooks 不如 classComponent, state 的可剥离也是其中一点, 不过对于这点我持不同看法, 至少在我看来, 带有 jsx 的是组件, 自定义 hook 也可以是组件, 2021 年了作为前端我们不应该在拘泥于组件只是一种带有 UI 内容的东西, 前端组件应该重新定义, 并且从提升代码可复用性的角度出发.

    *组件是可复用代码的一种封装性形式, 并不拘泥于封装的内容

    只是对于应用研发来说, 我们需要明确封装的方法, 从而减少封装组件的成本, 这好比如果一个仓库里有 1000 种打包的方式和箱子, 那么打包效率就会非常低下, 即使你封装了仓库里的所有东西.

    本文先不讨论对于封装形式和方法的定义, 仅仅从封装组件的角度去看 internal state, 如果你是一个经常给别人提供组件的人, 我想你一定会有一种困惑, 为什么我封装好的 react 组件总是无法满足他们的需求, 只要外部业务持续发展, 就会有各种各样的需求涌入你的组件, 而现有的组件封装技术都无法让你的组件具备很好的复用性, 当你提供的组件可扩展功能越多, 这个组件距离不可维护就更近了一步.

    这其中的关键其实就是大部分组件开发者开发的组件都轻易的被外部需求打破了封装, 影响了你内部的状态, 也就是 internal state, 当你把 state 看成是一种内部的部分, 那么那些传递进来的 external props 就不应该影响你的 internal state 的稳定.

    让我们来看一段代码, 更直观的理解这种被打破的封装

    
    function MyComponent(externalProps){
    	const [internalState, setInternalState] = useState(0)
        if(externalProps){
        	setInternalState(1)
        }else{
            setInternalState(2)
        }
    }
    
    

    我相信这种代码在我们开发的组件中大量存在, 我们虽然利用 React 的能力封装了 MyComponent, 但是对于 MyComponent 来说, externalProps 却能决定我们 internalState 到底是 1 还是 2.

    这种突破封装的控制, 还会影响所有 MyComponent 使用了 internalState 的逻辑, 如果这些逻辑再互相影响, 那么就会涟漪效应

    有人可能会说, 根据传入的参数实现不同的逻辑这似乎没问题呀? 如果这个组件只是一个单纯的没有自己核心逻辑的受控组件, 这自然没问题, 但事实上大多数组件都有一部分逻辑是和 externalProps 完全没有任何关系的. 就好比这样

    
    function MyComponent(externalProps){
    	const [internalState, setInternalState] = useState(0)
        const [internalState2, setInternalState2] = useState('only use internal')
        if(externalProps){
        	setInternalState(1)
        }else{
            setInternalState(2)
        }
        //todo code
        return(
        	<div>{internalState2}</div>
        )
    }
    
    

    如果未来的某一天, 你的同事需要复用你这些不受 externalProps 影响的代码, 你将面临比较头疼的重构, 但实际工作中我们其实没有足够的时间重构, 于是可选项就成了 copy, 或者通过一个特殊的 externalProps, 这种事我们俗称技术债务.

    实际的工程实践中, 真实代码远比我提供的示例代码复杂的多, 重构难度也大的多.

    尤其是在那些开发企业服务软件的领域, 业务逻辑繁多复杂, 各种定制化和标准化之间的冲突, 更进一步加剧了这个问题.

    为了解决这个问题, 我们通过实践结合 React hook 的特性, 构思了一种新的状态管理架构, 用于解决 internalState → externalProps → internalState → externalProps 之间互相影响的问题, 从而同时满足对消费 externalProps 逻辑的维护编写, 同时又确保对 internalState 的封装不被打破, 并围绕这种架构开发了一套新的框架.

    emem, 事实上我们利用了一种类似细胞膜的模式, 在 internalState 和 externalProps 之间加入了 membrane, 至于具体是如何做到的, 让我们再后面的文章里再聊聊, 如果你对此感兴趣的话 ?

    后话

    最近对 low code 又有了新理解, 用大白话说, 就是写更少的代码解决更多的问题, 如果你正在开发那种可视化搭建的系统, 通常我们管这个叫 low code, 我觉得你可以仔细思考下, 这套系统是否能解决更多的问题, 这个更多可以是量, 也可以是类型, 因为有时候我们所设想的理论上大量相同场景能够被搭建出来的这一判断, 在实践中往往是不存在的, 而这也就意味着 low code 赖以产生价值的稳定物料这个基础是不存在的.

    所以很多时候我们只看到了能写更少的代码, 却忽视了是否能解决更多的问题.


    起源地下载网 » 从工程实践来理解 React 中的 state 和 props

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元