最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • React16系列:船新的context

    正文概述 掘金(QZhan)   2020-12-10   558

    旧版context的问题

    众所周知 react 推荐的一个重要思想就是单向数据流,整个 react 应用要遵循数据从上到下的方向传递。这就造成了在多层组件嵌套的情况下,父组件的数据要传给最底层的组件的话就要经过多层中间组件的 props,造成了大量冗余的 props 声明(称为 props drilling 问题)。

    新旧 context 都是为了解决 props drilling 问题。但是在react 16.3之前的旧版 context 却破坏了 react 的分形架构思想。

    所谓分形就是指从 react 应用的组件树中抽取任意一部分都是可以直接运行的子组件树。

    但如果使用了旧版 context 语法,这个思想就被破坏了:

    enter code here
    class Button extends React.Component {
        render() {
            return (
                <button style={{color: this.context.color}}></button>
            )
        }
    }
    Button.contextType = {
        color: PropTypes.string
    }
    
    class Message extends React.Component{
        getChildContext() {
            return {color: 'red'}
        }
    
        render() {
            return (
                <Button />
            )
        }
    }
    
    Message.childContextTypes = {
        color: PropsTypes.string
    }
    

    上述代码中,父组件的getChildContext和子组件的this.context都非常 magic,也违背了分形的思想。

    旧版context的致命缺陷

    旧版 context 除了上述违背了分形思想的问题,还存在一个影响功能的致命缺陷。

    这个缺陷就是当 context 传递过程中某个组件在shouldComponentUpdate中返回 false 时,下面的组件将无法触发 rerender,从而导致新的 context 值无法更新到下面的组件。

    例如

    <A>
        <B>
            <C>
            </C>
        </B>
    </A>
    

    这种结构下中间的B组件一旦在 shouldComponentUpdate 返回 false,将导致C组件更新失败。

    新版context

    一个新的 api 出现肯定是为了解决某一个或某一类问题。

    基于这一思想,我们就很容易理解为什么 react 16要推出新的 context api 来解决上述旧版 context 的问题和缺陷。

    新的 context 提供了createContext方法来创建 context 对象,这个对象有 provider 生产者和 consumer 消费者两个属性。

    用法三步走: 1.创建一个 context

    const ColorContext = React.createContext('red'); // 默认red
    

    2.父组件使用 provider

    class Message extends React.Component {
        state = {
            color: 'green'
        }
        
        render() {
            return (
                <ColorContext.Provider value={this.state.color}>
                    <Button />
                </ColorContext.Provider>
            )
        }
    }
    

    3.子组件使用 consumer

    class Button extends React.Component {
        render() {
            return (
                <ColorContext.Consumer>
                    {
                        value => 
                        (<span style={{color: value}}></span>)
                    }
                </ColorContext.Consumer>
            )
        }
    }
    

    新 api 声明式地表达了组件使用了哪个 context 对象的 Provider 或者 consumer,从而符合了 react 的分形思想。

    另外新 api 不再依赖shouldComponentUpdate方法,Provider 通过 Object.is 来判断 props 是否发生变化,如果发生变化就把新值通知对应的 consumer 组件。

    这样旧版 api 的问题和缺陷就都解决了。

    context与redux

    redux 作为一个重量级的解决组件间通信的方案,可以说在 react 的数据管理生态中有着一统江湖的地位。

    而在新版 context 出现后,社区开始出现是否要使用新版 context 替代 redux 的疑问。

    在回答这个疑问前,我们可以先简单了解下 redux 和 react-redux 原理。

    react与redux

    终端应用的复杂性来源于大量无规律的交互动作和异步动作。而这些动作无时无刻地在改变应用的状态。

    redux 的设计初衷就是为了让开发者清晰地掌握状态变更,并且可以复现出来。

    redux 只负责很好地管理 store 这个数据仓库,但怎么把 store 里的数据传递给组件使用呢?这时候就需要用到 react-redux 了。

    这里不详细介绍 redux 和 react-redux 的语法,我们知道使用 react-redux 有两个核心步骤:

    1. 使用 provider 包裹根组件
    2. 使用 connect 连接子组件和 store

    此时我们会发现有个熟悉的名词 provider 出现了。

    没错,它就是上文提到的 context.provider。react-redux 正是使用了 react 的 context 语法,将 store 作为 context 值传递下去。

    然后在 connect 方法中从 context 中取出 store 的值并订阅 store 的变化,最后将该值通过 props 传给业务组件。

    繁琐与规范

    简单了解了 redux 和 react-redux 的原理后,我们可以发现 redux 这一套相当于 context +数据流管理。

    也就是说 context 是一个更加轻量版的数据管理方案。如果你的应用本身并不复杂,只需要有个地方来存放全局数据,那么 context 可能就已经满足了要求。

    但是应用复杂度提升后,复杂的 context 管理起来的难度也会直线提升。这时候使用 redux 约定的设计哲学和 api 可以帮助多人开发的复杂应用保持足够清晰和规范。

    总结来说,redux 的模板代码繁琐对应了 context 的简洁 api,前者的规范也对应了 context 的灵活散乱。

    技术没有银弹,只有根据具体的项目来进行技术选型才是最合适的。

    附录

    附上一份社区整理的redux最佳实践,方便大家更加了解redux的设计哲学:

    • 区分smart component(处理state变更)和dump component(只使用state,不关心变更)
    • component中不要出现async call,交给action creator。
    • reducer逻辑尽量简单只复制更新数据,复杂业务逻辑交给action creator。
    • reducer必须返回新的state对象。
    • action creator和reducer使用纯函数
    • 尽量让smart component来和store connect
    • 不要使用redux,除非应用的数据管理足够复杂混乱。

    起源地下载网 » React16系列:船新的context

    常见问题FAQ

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

    发表评论

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

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

    联系作者

    请选择支付方式

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