Javascript HOC-功能组件

Javascript HOC-功能组件,javascript,reactjs,components,higher-order-components,Javascript,Reactjs,Components,Higher Order Components,我已经在我的react应用程序中创建了一个HOC,它工作正常。然而,我想知道是否有一种方法可以创建一个HOC作为功能组件(有状态还是没有状态)???因为给定的示例是基于类的组件 试图在网上找到相同的内容,但什么也找不到。不确定这是否可能??还是做正确的事 任何潜在客户都会受到欢迎:)当然,您可以创建一个功能性无状态组件,该组件接受组件作为输入,并返回其他组件作为输出,例如 您可以创建一个PrivateRoute组件,该组件接受一个组件作为prop值,并根据用户是否经过身份验证返回一些其他组件 如

我已经在我的react应用程序中创建了一个HOC,它工作正常。然而,我想知道是否有一种方法可以创建一个HOC作为功能组件(有状态还是没有状态)???因为给定的示例是基于类的组件

试图在网上找到相同的内容,但什么也找不到。不确定这是否可能??还是做正确的事


任何潜在客户都会受到欢迎:)

当然,您可以创建一个功能性无状态组件,该组件接受组件作为输入,并返回其他组件作为输出,例如

  • 您可以创建一个PrivateRoute组件,该组件接受一个组件作为prop值,并根据用户是否经过身份验证返回一些其他组件
  • 如果用户未通过身份验证(从上下文存储中读取),则可以使用
    将用户重定向到登录页面,否则返回作为道具传递的组件,并将其他道具发送到该组件
  • App.js

    const-App=()=>{
    返回(
    );
    }
    导出默认应用程序;
    
    PrivateRoute.jsx

    import React,{useContext,useffect}来自“React”;
    从“react router dom”导入{Route,Redirect}
    从“../../context/auth/AuthContext”导入AuthContext
    const privaterout=({component:component,…rest})=>{
    const authContext=useContext(authContext)
    常量{loadUser,isAuthenticated}=authContext
    useffect(()=>{
    loadUser()
    //eslint禁用下一行
    }, [])
    如果(isAuthenticated==null){
    返回
    }
    返回(
    !我被认证了(
    ) : (
    )
    }
    />
    );
    };
    导出默认私有路由;
    

    高阶组件不必是类组件,它们的目的是根据某些逻辑将组件作为输入,并将组件作为输出返回。

    当然,您可以在react中创建功能性的HOC,也可以为其创建任何其他文件夹,如“Utils”。例如,它是Utils文件夹中的my amountUtil.js文件:

    导出常量getFormattedAmount=(金额?:金额)=>( 金额&
    ${amount.formattedAmount}${amount.currency}
    );

    我同意,严格地说,这个例子不是一个真正的例子。HOC的区别在于它返回一个组件,而接受答案中的
    privaterote
    组件本身就是一个组件。因此,虽然它很好地完成了它开始要做的事情,但我不认为这是一个很好的HOC示例

    在功能组件世界中,最基本的HOC如下所示:

    const withNothing = Component => ({ ...props }) => (
      <Component {...props} />
    );
    
    使用这种方法的一种方法是,如果您想使用特别(没有双关语的lol)上下文提供程序

    假设我的应用程序有多个用户可以登录的点。我不想在所有这些点上复制登录逻辑(API调用和成功/错误消息),所以我想要一个可重用的
    组件。然而,在我的例子中,所有这些登录点在视觉上都有很大的不同,所以可重用组件不是一个选项。我需要的是一个可重用的
    组件,它将为其子组件提供所有必要的功能—API调用和成功/错误消息。有一种方法可以做到这一点:

    // This context will only hold the `login` method.
    // Calling this method will invoke all the required logic.
    const LoginContext = React.createContext();
    LoginContext.displayName = "Login";
    
    // This "HOC" (not a true HOC yet) should take care of
    // all the reusable logic - API calls and messages.
    // This will allow me to pass different layouts as children.
    const WithLogin = ({ children }) => {
      const [popup, setPopup] = useState(null);
    
      const doLogin = useCallback(
        (email, password) =>
          callLoginAPI(email, password).then(
            () => {
              setPopup({
                message: "Success"
              });
            },
            () => {
              setPopup({
                error: true,
                message: "Failure"
              });
            }
          ),
        [setPopup]
      );
    
      return (
        <LoginContext.Provider value={doLogin}>
          {children}
    
          {popup ? (
            <Modal
              error={popup.error}
              message={popup.message}
              onClose={() => setPopup(null)}
            />
          ) : null}
        </LoginContext.Provider>
      );
    };
    
    // This is my main component. It is very neat and simple
    // because all the technical bits are inside WithLogin.
    const MyComponent = () => {
      const login = useContext(LoginContext);
    
      const doLogin = useCallback(() => {
        login("a@b.c", "password");
      }, [login]);
    
      return (
        <WithLogin>
          <button type="button" onClick={doLogin}>
            Login!
          </button>
        </WithLogin>
      );
    };
    
    然后:

    const MyComponent = () => {
      const login = useContext(LoginContext);
    
      const doLogin = useCallback(() => {
        login("a@b.c", "password");
      }, [login]);
    
      return (
        <button type="button" onClick={doLogin}>
          Login!
        </button>
      );
    };
    
    const MyComponentWithLogin = withLogin(MyComponent);
    
    constmycomponent=()=>{
    const login=useContext(LoginContext);
    const doLogin=useCallback(()=>{
    登录(“a@b.c“,”密码“);
    },[登录];
    返回(
    登录!
    );
    };
    常量MyComponentWithLogin=withLogin(MyComponent);
    
    MyComponentWithLogin
    现在将按预期工作

    这可能不是处理这种特殊情况的最佳方式,但我有点喜欢

    是的,它实际上只是一个额外的函数调用,仅此而已!根据官方指南:

    HOC本身不是React API的一部分。它们是从React的组成性质中产生的一种模式


    下面是一个将HOC与功能组件结合使用的过于简化的示例

    要“包装”的功能组件:

    import React from 'react'
    import withClasses from '../withClasses'
    
    const ToBeWrappedByHOC = () => {
    return (
        <div>
            <p>I'm wrapped by a higher order component</p>
        </div>
           )
    }
    
    export default withClasses(ToBeWrappedByHOC, "myClassName");
    
    import React from 'react'
    
    
    const withClasses = (WrappedComponent, classes) => {
    return (props) => (
        <div className={classes}>
            <WrappedComponent {...props} />
        </div>
           );
    };
    
    export default withClasses;
    
    从“React”导入React
    从“../withClasses”导入withClasses
    常数ToBeWrappedByHOC=()=>{
    返回(
    我被一个高阶组件包住了

    ) } 导出带有类的默认值(ToBeWrappedByHOC,“myClassName”);
    高阶组件:

    import React from 'react'
    import withClasses from '../withClasses'
    
    const ToBeWrappedByHOC = () => {
    return (
        <div>
            <p>I'm wrapped by a higher order component</p>
        </div>
           )
    }
    
    export default withClasses(ToBeWrappedByHOC, "myClassName");
    
    import React from 'react'
    
    
    const withClasses = (WrappedComponent, classes) => {
    return (props) => (
        <div className={classes}>
            <WrappedComponent {...props} />
        </div>
           );
    };
    
    export default withClasses;
    
    从“React”导入React
    常量withClasses=(WrappedComponent,classes)=>{
    返回(道具)=>(
    );
    };
    导出默认类;
    
    该组件可以在其他组件中使用,如下所示

    <ToBeWrappedByHOC/>
    
    
    
    它看起来更像一个HOC组件,更像一个包装器组件。HOC返回FC not REACTION元素。如果我想在此处设置管理路由,该怎么办?我该怎么做?那么你的应用程序是否支持多重授权,例如用户和管理员?如果是这样,您可以创建一个名为的组件,并检查person是否为admin(而不是此处的isAuthenticated),这样只有拥有属性admin的人(从身份验证的响应中检查)才能访问该组件。请参阅下面的答案并修改您的答案或删除。感谢您试图提供帮助,但回答有误导性。私有路由并没有返回一个组件,这听起来很奇怪。在这种情况下,组件是道具的功能,而不是某些JSX的结果。