专栏首页菜鸟计划react入门(六):状态提升&context上下文小白速懂

react入门(六):状态提升&context上下文小白速懂

一、状态提升

使用 react 经常会遇到几个组件需要共用状态数据的情况。这种情况下,我们最好将这部分共享的状态提升至他们最近的父组件当中进行管理。

原理:父组件基于属性把自己的一个fn函数传递给子组件,子组件在某些操作下把fn执行,在执行fn的过程中把父组件中的一些属性信息进行了修改,从而影响相关子组件的重新渲染。

直接看代码

<Vote title={'标题一'}></Vote>  //调用

vote.js文件
import React from 'react';
import VoteHeader from './voteHeader.js'
import VoteBody from './voteBody.js'
import VoteFooter from './voteFooter.js'
class Vote extends React.Component{
    constructor(){
        super()
        this.state = {
            n: 0,
            m: 0
        }
    }
    handleNum = (type)=> {
        if (type === 1) {
            this.setState({
                n: this.state.n+1
            })
        } else {
            this.setState({
                m: this.state.m+1
            })
        }
    }
    render() {
        let {title} = this.props;
        let {n, m} = this.state;
        let {handleNum} = this;
        return (
            <div>
                <VoteHeader title={title}></VoteHeader>
                <VoteBody n={n} m={m}></VoteBody>
                //将父组件函数传递给子组件调用
                <VoteFooter handleNum={handleNum}></VoteFooter>
            </div>
        )
    }
}
export default Vote;


VoteHeader.js文件
import React from 'react';
class VoteHeader extends React.Component{
    constructor(){
        super()
    }
    render() {
        let {title} = this.props;
        return (
            <div>{title}</div>
        )
    }
}
export default VoteHeader;


VoteBody.js文件
import React from 'react';
class VoteBody extends React.Component{
    constructor(){
        super()
    }
    render() {
        let {n, m} = this.props;
        return (
            <div>
                <div>赞成{n}票</div>
                <div>反对{m}票</div>
            </div>
        )
    }
}
export default VoteBody;


VoteFooter.js文件
import React from 'react';
class VoteFooter extends React.Component{
    constructor(){
        super()
    }
    render() {
        let {handleNum} = this.props;
        return (
            <div>
            //这个地方通过操作父组件函数改变父组件的属性值
                <button onClick={e => handleNum(1)}>赞成</button>
                <button onClick={e => handleNum(0)}>反对</button>
            </div>
        )
    }
}
export default VoteFooter;

二、context上下文

基于上下文管理组件信息的传递

上下文也是依托组件嵌套关系完成的,它的优势在于:当前组件(祖先组件)设置一些上下文,后代所有组件(儿子或孙子等)都可以随时获取使用,而不需要调取组件的时候层层传递。

直接看代码

<Vote title={'标题一'}></Vote>  //调用

vote.js文件
import React from 'react';
import PropTypes from 'prop-types';
import VoteHeader from './voteHeader1.js'
import VoteBody from './voteBody1.js'
import VoteFooter from './voteFooter1.js'
class Vote extends React.Component{
    //设置后代需要使用的上下文及类型
    static childContextTypes = {
        title: PropTypes.string,
        n: PropTypes.number,
        m: PropTypes.number,
        handleNum: PropTypes.func
    }
    //获取后代需要的上下文信息(可以把这个方法理解为一个生命周期函数,在每一次render之前执行,return的值就是后期需要用到的上下文具体信息值)
    getChildContext(){
        let {title} = this.props;
        let {n, m} = this.state;
        let {handleNum} = this;
        return {
            title,
            n,
            m,
            handleNum
        }
    }
    constructor(){
        super();
        this.state = {
            n: 0,
            m: 0
        }
    }
    handleNum = (type)=> {
        if (type === 1) {
            this.setState({
                n: this.state.n+1
            })
        } else {
            this.setState({
                m: this.state.m+1
            })
        }
    }
    render() {
        return (
            <div>
                //这里就不需要再手动传递props了
                <VoteHeader></VoteHeader>
                <VoteBody></VoteBody>
                <VoteFooter></VoteFooter>
            </div>
        )
    }
}
export default Vote;


VoteHeader.js文件
import React from 'react';
import PropTypes from "prop-types"
class VoteHeader extends React.Component{
    //在后代组件中,我们需要用到哪些上下文信息,一定要指定当前需要使用的信息值类型(而且必须和祖先指定的一样),否者无法基于context获取
    static contextTypes = {
        title: PropTypes.string
    }
    constructor(){
        super()
    }
    render() {
        return (
            //通过上下文的值来进行渲染
            <div>{this.context.title}</div>
        )
    }
}
export default VoteHeader;


VoteBody.js文件
import React from 'react';
import PropTypes from "prop-types"
class VoteBody extends React.Component{
    static contextTypes = {
        n: PropTypes.number,
        m: PropTypes.number
    }
    constructor(){
        super()
    }
    render() {
        let {n, m} = this.context;
        return (
            <div>
                <div>赞成{n}票</div>
                <div>反对{m}票</div>
            </div>
        )
    }
}
export default VoteBody;


VoteFooter.js文件
import React from 'react';
import PropTypes from "prop-types";
class VoteFooter extends React.Component{
    static contextTypes = {
        handleNum: PropTypes.func,
    }
    constructor(){
        super()
    }
    render() {
        let {handleNum} = this.context;
        return (
            <div>
                <button onClick={e => handleNum(1)}>赞成</button>
                <button onClick={e => handleNum(0)}>反对</button>
            </div>
        )
    }
}
export default VoteFooter;

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • react入门(三):state、ref & dom简解

    作用:组件内部的状态重新更新时,可以控制组件内部重新渲染(不需要重新调取组件也可以重新渲染)

    柴小智
  • 写一个简单的轮播组件

    柴小智
  • JSX渲染原理

    1.基于babel-preset-react-app这个语法解析包,把jsx语法转换成一个名为 React.createElement() 的方法调用。

    柴小智
  • 2019前端面试基础题集合!赶紧上车!快!快!快!

    在 ES5.1 里面函数是这样执行的(不讨论use strict和一些特殊情况,JS好复杂的),按如下顺序执行:

    用户1272076
  • jquery 元素节点操作 - 创建节点、插入节点、删除节点

    前面的篇章对于jquery的元素操作大部分是使用html()的方式来操作,这种直接使用字符串创建的方式也是性能最高的。

    Devops海洋的渔夫
  • react实战:umi问卷发布系统

    技术团队中,保持技术分享和持续的学习是完全必要的。企业主会说:"公司不是培训机构。"这固然正确。但一个公司,总会遇到这种或那种需要攻关的难题。当你不愿意分享解决...

    一粒小麦
  • js写插件教程

    连小壮
  • 发布一个日期选择控件(ASPNET2.0)

    The Coolest DHTML Calendar,这是一个在GPL下发布的JS日历程序,具有极高的可配置性,包括外观样式、显示格式、显示内容等等。默认程序...

    张善友
  • 安卓逆向系列教程 4.3 登山赛车内购破解

    首先在这里下载游戏:http://g.10086.cn/game/760000032287?spm=www.pdindex.android.addjgame.1

    ApacheCN_飞龙
  • CA数字签名的由来

    上一次内容我们介绍了TLS加密原理,为什么要加密通信呢?是因为我们不希望我们的个人信息被明文传播,任何一个人只要截断我们的物理线路或者入侵到我们网络中,就能获取...

    运维部落

扫码关注云+社区

领取腾讯云代金券