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

前端之家收集整理的这篇文章主要介绍了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>
    );
  }
}
@H_301_155@//重点
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 {
@H_301_155@//重点
  getChildContext() {
    return {color: "purple"};
  }

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

@H_301_155@//重点
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,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';@H_301_155@//这个是用来识别是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组件

猜你在找的React相关文章