代码之家  ›  专栏  ›  技术社区  ›  Leff

用上下文API示例解释React高阶组件

  •  2
  • Leff  · 技术社区  · 6 年前

    我试图理解一个使用上下文api的高阶组件的例子 here .

    因为,我对react和函数式编程还很陌生,所以我不明白这里的东西到底是怎么工作的。我们正在向函数发送一个函数 withUser props

    function withUser(Component) {
      return function ConnectedComponent(props) {
        return (
          <UserContext.Consumer>
            {user => <Component {...props} user={user} />}
          </UserContext.Consumer>
        );
      };
    }
    

    UserAvatar 我们正在传递接收 ,并返回 img .

    const UserAvatar = withUser(({ user, size }) => (
      <img
        className={`user-avatar ${size || ""}`}
        alt="user avatar"
        src={user.avatar}
      />
    ));
    

    所以,基本上在这之后我们可以想象 用户头像 成为:

    const UserAvatar = props => {
            return (
              <UserContext.Consumer>
                {user => <Component {...props} user={user} />}
              </UserContext.Consumer>
            );
          };
    

    Component

    ({ user, size }) => (
          <img
            className={`user-avatar ${size || ""}`}
            alt="user avatar"
            src={user.avatar}
          />
        )
    

    我希望到目前为止这是对的,但我不明白的是这句话:

    {user => <Component {...props} user={user} />}
    

    为什么我们需要把它作为一个函数,而不只是返回组件,当我们有 道具 已经和正在通过 user 用户头像 UserStats 组件?

    const UserStats = () => (
      <UserContext.Consumer>
        {user => (
          <div className="user-stats">
            <div>
              <UserAvatar user={user} />
              {user.name}
            </div>
            <div className="stats">
              <div>{user.followers} Followers</div>
              <div>Following {user.following}</div>
            </div>
          </div>
        )}
      </UserContext.Consumer>
    );
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Jared Smith    6 年前

    也许最简单的方法是描述一个类似的概念:函数装饰器。

    // Start with a function, any function.
    let add = (a, b) => a + b;
    

    但是现在我们要为参数添加日志并返回:

    let addWithLogging = (a, b) => {
      console.log("Args are ", a, b);
      const result = a + b;
      console.log("Result is ", result);
      return result;
    }
    

    但是等等,这是JavaScript,我们有更高阶的函数,可以提取一个decorator:

    // Here we take a function f and wrap it. We'll return a function that will
    // collect the arguments, log them, perform f on them, log the result, and
    // then finally return that result to the caller.
    const withLogging = f => (...args) => {
      console.log("Args are ", ...args);
      const result = f(...args);
      console.log("Result is ", result);
      return result;
    };
    
    addWithLogging = withLogging(add);
    

    你呢 只需将UserContext组件作为另一个组件返回的JSX的一部分:

    const UserAvatar = ({ user, size }) => (
      <UserContext.Consumer>
        <img
          className={`user-avatar ${size || ""}`}
          alt="user avatar"
          src={user.avatar}
        />
      </UserContext.Consumer>
    );
    

    但是现在,就像在日志示例中一样,您在每个需要它的组件中重复样板文件。

    user 已经在 props 渲染组件时。供参考,以下是 compiled JSX .

    应该仔细阅读代码。

    用户 通过上下文提供程序进行注入,唯一的方法是为它提供一个传递参数的函数。