父->子

父组件将要传递的数据放到子组件的属性上,

// 父组件
class Father extends Component {
  
  render() {
    <Son message="msg from father" />
  }
}

子组件通过props获取这个值

// 子组件
class Son extends Component {
  constructor(props) {
    super(props)
  }
  
  render() {
    <div>
        {this.props.message}
    </div>
  }
}

子->父

子组件向父组件传值使用回调函数,父组件先向子组件传递一个函数,

// 父组件
sonHandler(msg) {
  this.setState({
    message: msg
  })
}

render() {
  return <div>
    {/*<Redirect />*/}
    <h2>{this.state.message}</h2>
    <Son click={this.sonHandler.bind(this)} />
  </div>
}

然后子组件中触发这个函数,并携带参数,就可以实现将子组件中的数据传递到父组件中

callback = (msg) => {
  return () => {
    this.props.click(msg)
  }
}

render() {
  return <div>
    <button onClick={this.callback('msg from son')}>click</button>
  </div>
}

祖先->后代

祖先到后代之间的传递方式有两种:中间层逐层props和使用context对象。逐层传递在层级较深时会变得很复杂,所以我们只使用context方法。

使用方法:上级组件声明自己支持context,提供一个context对象;子级组获取context

// 为当前的 theme 创建一个 context(“light”为默认值)。
const ThemeContext = React.createContext('light');
// 父组件
class App extends React.Component {
  render() {
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// 子组件
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

// 孙子组件(类组件)
class ThemedButton extends React.Component {
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}
// 孙子组件(函数组件)
export default function ThemedButton() {
  return (
      <ThemeContext.Consumer>
        {theme => (
          <Button theme={theme} />
      )}
    </ThemeContext.Consumer>
  )
}

API

React.createContext

创建一个context对象,返回一个Provider,可以设置默认值,当组建没有被Provider包裹时,会使用默认值

Context.Provider

接收一个value属性,传递给消费组件,有多层Provider包裹时,最内层的组件会覆盖其他

Context.Consumer

接收context的值,传递给函数的 value 值等同于往上组件树离这个 context 最近的 Provider 提供的 value 值

Class.contextType

挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* 在组件挂载完成后,使用 MyContext 组件的值来执行一些有副作用的操作 */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* 基于 MyContext 组件的值进行渲染 */
  }
}
MyClass.contextType = MyContext;

前端小白