zoukankan      html  css  js  c++  java
  • 关于react16.4——上下文Context

    首先我们来聊一聊(上下文)Context。

    上下文(Context) 提供了一种通过组件树传递数据的方法,无需在每个级别手动传递 props 属性。

    在典型的 React 应用程序中,数据通过 props 自上而下(父到子)传递,但对于应用程序中许多组件所需的某些类型的 props(例如环境偏好,UI主题),这可能很麻烦。 上下文(Context) 提供了在组件之间共享这些值的方法,而不必在树的每个层级显式传递一个 prop 。

    1.何时使用Context

    Context 旨在共享一个组件树内可被视为 “全局” 的数据,例如当前经过身份验证的用户,主题或首选语言等。

    API:

      React.createContext:创建一个 { Provider, Consumer } 对。当 React 渲染 context Consumer 时,它将从组件树中匹配最接近的 Provider 中读取当前的 context 值。

    const {Provider, Consumer} = React.createContext(defaultValue);

      Provider:React组件允许 Consumer(使用者) 订阅 context 的改变。 一个 Provider 可以连接到许多 Consumers 。

    <Provider value={/* some value */}>

      Consumer:一个可以订阅 context 变化的 React 组件。需要接收一个 函数作为子节点。 该函数接收当前 context 值并返回一个 React 节点

    <Consumer>
      {value => /* render something based on the context value */}
    </Consumer>

    只要 Provider 的 value 属性发生变化是,所有属于该 Provider 后代的 Consumers 就会重新渲染。 从 Provider 到它的后代 Consumers 的传播不受 shouldComponentUpdate 方法的约束, 所以即使当祖先组件退出更新时,后代 Consumer 也会被更新。

    例如,

    const ThemeContext = React.createContext('light');
    
    class App extends React.Component {
      render() {
        //
        return (
          <ThemeContext.Provider value="dark">
          <Toolbar />
          </ThemeContext.Provider>
        );
      }
    }
    
    function Toolbar(props) {
      return (
        <div>
          <ThemedButton />
        </div>
      );
    }
    
    function ThemedButton(props) {
      //
      return (
        <ThemeContext.Consumer>
        {theme => <Button {...props} theme={theme} />}
        </ThemeContext.Consumer>
      );
    }

    当一些数据需要在不同的嵌套级别上被许多组件访问时,首先考虑使用 Context 。 请谨慎使用它,因为它使组件重用更加困难。

    如果你只想避免在多个级别上传递一些 props ,那么 组件组合 通常比 Context 更简单。

    2.在生命周期中访问Context

    不是将 context 添加到每个生命周期方法中, 你只需将它作为 props , 然后像使用 props 一样使用它即可。

    例如,

    class Button extends React.Component {
      componentDidMount() {
        // ThemeContext的值为this.props.theme
      }
    
      componentDidUpdate(prevProps, prevState) {
        // 之前的ThemeContext的值为prevProps.theme
        // 新的ThemeContext的值为this.props.theme
      }
    
      render() {
        const {theme, children} = this.props;
        return (
          <button className={theme || 'light'}>
            {children}
          </button>
        );
      }
    }
    
    export default props => (
      <ThemeContext.Consumer>
        {theme => <Button {...props} theme={theme} />}
      </ThemeContext.Consumer>
    );

    3.高阶组件中的Context

    如果我们想在很多的地方使用ThemContetx,可以创建一个高阶组件在其中使用,如,

    const ThemeContext = React.createContext('light');
    
    // 这个方法接收一个component
    export function withTheme(Component) {
      // 然后返回另一个component
      return function ThemedComponent(props) {
        // 并且渲染一个包含context theme的包装组件
        return (
          <ThemeContext.Consumer>
            {theme => <Component {...props} theme={theme} />}
          </ThemeContext.Consumer>
        );
      };
    }

    那么现在,任何依赖于theme context的组件都可以使用创建的withTheme函数轻松订阅它,

    function Button({theme, ...rest}) {
      return <button className={theme} {...rest} />;
    }
    
    const ThemedButton = withTheme(Button);

    4.转发 Refs 给 context Consumer(使用者)

    渲染 prop(属性) API的一个问题是 refs 不会自动传递给封装元素。 为了解决这个问题,使用 React.forwardRef

    /*fancy-button.js*/
    class FancyButton extends React.Component { focus() {
    // ... } // ... } // 使用context传递当前的theme给FancyButton. // 使用forwardRef更好的传递refs给FancyButton export default React.forwardRef((props, ref) => ( <ThemeContext.Consumer> {theme => ( <FancyButton {...props} theme={theme} ref={ref} /> )} </ThemeContext.Consumer> ));
    /*app.js*/
    import FancyButton from './fancy-button'; const ref = React.createRef(); // 我们的ref将指向FancyButton组件, // 并且没有ThemeContext.Consumer包裹它. // 这意味着我们可以在FancyButton上应用方法,就像ref.current.focus()这样 <FancyButton ref={ref} onClick={handleClick}> Click me! </FancyButton>;
  • 相关阅读:
    [原]Unity3D深入浅出
    [原]Unity3D深入浅出
    [原]Unity3D深入浅出
    [原]Unity3D深入浅出
    [原]Unity3D深入浅出
    [原]Unity3D深入浅出
    [原]Unity3D深入浅出
    SSH 远程端口转发
    SSH 本地端口转发
    SSH执行远程命令和传送数据
  • 原文地址:https://www.cnblogs.com/zyl-Tara/p/9718970.html
Copyright © 2011-2022 走看看