我已经在我的 React 应用程序中创建 了 一个 HOC,并且它工作正常。但是我想知道是否有办法将 HOC 创建为功能组件(有或没有状态)???因为给定的示例是基于类的组件。
试图在网上找到同样的东西,但什么也找不到。不确定那是否可能?或者做正确的事?
任何线索将不胜感激:)
原文由 Mohammed Amir Ansari 发布,翻译遵循 CC BY-SA 4.0 许可协议
我已经在我的 React 应用程序中创建 了 一个 HOC,并且它工作正常。但是我想知道是否有办法将 HOC 创建为功能组件(有或没有状态)???因为给定的示例是基于类的组件。
试图在网上找到同样的东西,但什么也找不到。不确定那是否可能?或者做正确的事?
任何线索将不胜感激:)
原文由 Mohammed Amir Ansari 发布,翻译遵循 CC BY-SA 4.0 许可协议
我同意 siraj ,严格来说, 接受的答案 中的示例不是真正的 HOC。 HOC 的显着特征是它 返回一个 component ,而接受答案中的 PrivateRoute
组件本身 就是 一个组件。因此,虽然它完成了它设定的目标,但我认为它不是 HOC 的一个很好的例子。
在功能组件世界中,最基本的 HOC 看起来像这样:
const withNothing = Component => ({ ...props }) => (
<Component {...props} />
);
调用 withNothing
返回另一个组件(不是实例,这是主要区别),然后可以像常规组件一样使用它:
const ComponentWithNothing = withNothing(Component);
const instance = <ComponentWithNothing someProp="test" />;
使用此方法的一种方法是,如果您想使用临时(没有双关语, _哈哈_)上下文提供程序。
假设我的应用程序有多个用户可以登录的点。我不想在所有这些点上复制登录逻辑(API 调用和成功/错误消息),所以我想要一个可重用的 <Login />
组件。然而,在我的例子中,所有这些登录点在视觉上都有很大不同,因此可重用组件不是一个选项。我需要的是一个可重用的 <WithLogin />
组件,它将为其子组件提供所有必要的功能 - 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>
);
};
不幸的是,这不起作用,因为 LoginContext.Provider
在 MyComponent
--- 中实例化,所以 useContext(LoginContext)
什么都不返回。
HOC 来救援!如果我添加一个小中间人怎么办:
const withLogin = Component => ({ ...props }) => (
<WithLogin>
<Component {...props} />
</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);
砰! MyComponentWithLogin
现在将按预期工作。
这可能不是解决这种特殊情况的最佳方式,但我有点喜欢它。
是的,它真的只是一个额外的函数调用,仅此而已!根据官方指南:
HOC 本身并不是 React API 的一部分。它们是一种从 React 的组合性质中浮现出来的模式。
原文由 Avius 发布,翻译遵循 CC BY-SA 4.0 许可协议
13 回答13k 阅读
7 回答2.2k 阅读
3 回答1.3k 阅读✓ 已解决
6 回答1.3k 阅读✓ 已解决
2 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
6 回答1.1k 阅读
当然,您可以创建一个功能性无状态组件,它接受组件作为输入并返回其他组件作为输出,例如;
<Redirect to='/login'/>
否则您返回作为道具传递的组件并将其他道具发送到该组件<Component {...props} />
应用程序.js
PrivateRoute.jsx
Higher Order Components不一定是类组件,它们的目的是将一个Component作为输入,按照某种逻辑返回一个组件作为输出。