React+DvaJs 之 Context与Props

本文探讨了在React和Dva.js中如何利用Context进行数据传递,以简化多层级组件间props的传递。内容包括传统的props传递方式的繁琐性,Context的使用方法,如何在组件生命周期方法中访问Context,以及无状态函数式组件如何利用Context。同时强调了Context作为实验性功能的潜在问题,并提供了一些最佳实践。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Context

React 遵循 Flux 思想进行数据流传递的时候,常见的方式是通过props 逐层从父级向子组件传递。

context 是实验功能,可以简化传递过程,尤其是组件树层数很多的时候,但是不容易发现传递的流向,所以谨慎使用

传统的props传值

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} />
    );
    return <div>{children}</div>;
  }
}

这个例子中,就是从Message 组件传递button组件的 color属性来实现主题控制,整个传递过程有些繁琐,如果使用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) =>
      <Message text={message.text} />
    );
    return <div>{children}</div>;
  }
}

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

通过给MessageList 添加childContextTypesgetChildContext,可以自动在组件树的运行上下文环境中传递值,作为父级设置值的时候,父级组件只能以类的形式声明,无状态函数式声明不可以。
子组件随后就可以使用context获取,但是必须定义 contextTypes,负责获取的是空对象。组件的声明就没有父组件的限制,可以是无状态函数式(stateless functional),或类。

各组件生命周期方法中的context

如果contextTypes在组件内部定义的话,下面生命周期函数将额外多一个参数(context对象)

void componentWillReceiveProps(
  object nextProps, object nextContext
)

boolean shouldComponentUpdate(
  object nextProps, object nextState, object nextContext
)

void componentWillUpdate(
  object nextProps, object nextState, object nextContext
)

void componentDidUpdate(
  object prevProps, object prevState, object prevContext
)

无状态函数式组件使用 context样例:

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

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

更新context

stateprops改变时会自动调用getChildContext,为了更新context中的数据,可以使用this.setState来触发局部state更新,这种更新会传递到所有子节点。

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';
      if (type !== this.state.type) {
        this.setState({type});
      }
    };

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

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

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

如果没看懂或者有任何,可以看看facebook 原版文章,欢迎留言交流

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值