React学习之进阶上下文(十九)

React中很容易根据组件从而跟踪数据流,当你使用一个组件时,可以通过看props来判断用了哪一些东西。

有时候你想直接通过组件树来讲数据传递子元素,而不是通过props一层一层的传递下去,可以使用React提供的contextAPI来处理。

1.为什么一般都不使用Context

虽然React提供了context来处理以上事件 ,但是一般情况下是不需要使用这个API的。

如果你想要你的应用尽可能的稳定的话,请不要使用Context,因为这在React属于一种实验性质的API,在未来的React版本中可能被抛弃。

如果你不是一个非常有经验的开发人员,也请不要使用context,通常都有更好方法来实现我们的要求

如果你硬是要用Context,请在小范围中使用

2.使用context的方法

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.props.color}}>
        {this.props.children}
      </button>
    );
  }
}

class Message extends React.Component {
  render() {
    return (
      <div>
        {this.props.text} <Button color={this.props.color}>Delete</Button>
      </div>
    );
  }
}

class MessageList extends React.Component {
  render() {
    const color = "purple";
    const children = this.props.messages.map((message) =>
      <Message text={message.text} color={color} key={index} />
    );
    return <div>{children}</div>;
  }
}

上面的我们给button设置颜色,竟然要从顶层的组件一步一步的通过props传递下去,很烦。

如果是使用context就会非常简单了

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
}
//重点
Button.contextTypes = {
  color: React.PropTypes.string
};
class Message extends React.Component {
  render() {
    return (
      <div>
        {this.props.text} <Button>Delete</Button>
      </div>
    );
  }
}
class MessageList extends React.Component {
//重点
  getChildContext() {
    return {color: "purple"};
  }

  render() {
    const children = this.props.messages.map((message, index) =>
      <Message text={message.text} key={index}/>
    );
    return <div>{children}</div>;
  }
}

//重点
MessageList.childContextTypes = {
  color: React.PropTypes.string
};

通过childContextTypesgetChildContextMessageList增加context上下文,React会自动将它传递给子组件,如果子组件设置了contextTypes就会获取到这个上下文。如果子组件的contextTypes没有设置的话,context就会是一个空的。

3.父子耦合

context可以让父组件和子组件建立一个直接数据交流的通道,React Router V4就实现了这个功能,这里不详讲。

4.在生命周期函数中使用context

需要将context通过参数传递

constructor(props, context)

componentWillReceiveProps(nextProps, nextContext)

shouldComponentUpdate(nextProps, nextState, nextContext)

componentWillUpdate(nextProps, nextState, nextContext)

componentDidUpdate(prevProps, prevState, prevContext)

上面这些函数以后会讲解

5.无状态函数式组件中的context

这里先声明一下函数式组件本身无法使用this.state来进行状态标记控制

const Button = ({children}, context) =>
  <button style={{background: context.color}}>
    {children}
  </button>;

Button.contextTypes = {color: React.PropTypes.string};

当我们将context当做参数传入函数式组件,并且contextTypes进行了类型检测控制,就可以在函数式组件内部使用context

6.更新Context

虽然React有更新Context的函数,但是对不起,依旧不希望你去使用context,这算是警告中的警告了。

在前面写的时候,我就已经使用getChildContext来处理数据,这个函数会在stateprops改变时被调用。只要对stateprops进行更新就可以实现context的更新。

class MediaQuery extends React.Component {
  constructor(props) {
    super(props);
    this.state = {type:'desktop'};
  }

  getChildContext() {
    return {type: this.state.type};
  }

  componentDidMount() {
    const checkMediaQuery = () => {
      const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';//这个是用来识别是PC端还是移动端(IE10+)
      if (type !== this.state.type) {
        this.setState({type});
      }
    };

    window.addEventListener('resize', checkMediaQuery);
    checkMediaQuery();
  }

  render() {
    return this.props.children;
  }
}

MediaQuery.childContextTypes = {
  type: React.PropTypes.string
};

当然使用这个更新也会出问题,就是我们的shouldComponentUpdate函数返回false的时候,会导致子组件不更新状态,从而让子组件的context超出控制。

下一篇将讲React中的WEB组件

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值