javascript - HOC - 功能组件
问题描述
我已经在我的反应应用程序中创建了一个 HOC ,并且它工作正常。但是我想知道是否有办法将 HOC 创建为功能组件(有或没有状态)???因为给定的示例是基于类的组件。
试图通过网络找到相同的内容,但什么也得不到。不确定那是否可能?还是永远做对的事??
任何线索将不胜感激:)
解决方案
我同意siraj的观点,严格来说,接受的答案中的示例不是真正的 HOC。HOC 的显着特征是它返回一个组件,而PrivateRoute
接受的答案中的组件是一个组件本身。因此,虽然它完成了它打算做的事情,但我不认为它是 HOC 的一个很好的例子。
在功能组件世界中,最基本的 HOC 如下所示:
const withNothing = Component => ({ ...props }) => (
<Component {...props} />
);
调用withNothing
返回另一个组件(不是实例,这是主要区别),然后可以像常规组件一样使用它:
const ComponentWithNothing = withNothing(Component);
const instance = <ComponentWithNothing someProp="test" />;
使用它的一种方法是,如果您想使用 ad-hoc(没有双关语lol)上下文提供程序。
假设我的应用程序有多个用户可以登录的点。我不想在所有这些点上复制登录逻辑(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 的组合性质中出现的一种模式。
推荐阅读
- ios - Xcode 11 模拟器一直崩溃
- python - 如何从csv中删除逗号和括号
- azure - Azure YAML 条件表达式 Powershell 任务
- android - 如何使用用户的位置来显示他们附近或半径范围内的信息?
- node.js - 如何以正确的方式验证和处理错误?
- python - 是否有用于“信息符号”的 gdb python API?
- java - Branch.io API 在创建时抛出 SSLException Unsupported record version Unknown-0.0
- python - Pandas 根据多个条件对 DataFrame 进行排序
- asp.net-mvc - 无法获得运行 if 语句并转到已登录部分的操作结果
- mysql - 为什么我收到此查询的错误 1054?有没有更有效的方法来编写这个查询?