javascript - Is it possible to use React Hooks outside of functional component, or i have to use mobx or redux?
问题描述
I am new to React, and when I was reading about the docs, I found there were two ways to implement React components, functional-based and class-based. I know before React 16.8 it's not possible to manage state in functional components, but after that there is React Hooks.
The problem is, there seems to be one restriction for React Hooks, they can only be used inside functional components. Take a server-client as an example, which needs to change an isAuthenticated
state while 401 received.
//client.js
import { useUserDispatch, signOut } from "auth";
export function request(url, args) {
var dispatch = useUserDispatch();
return fetch(url, args).then(response => {
if (response.status === 401) {
logout(dispatch);
}
}
);
//auth.js
import React from "react";
var UserStateContext = React.createContext();
var UserDispatchContext = React.createContext();
function userReducer(state, action) {
...
}
function UserProvider({ children }) {
var [state, dispatch] = React.useReducer(userReducer, {
isAuthenticated: false,
});
return (
<UserStateContext.Provider value={state}>
<UserDispatchContext.Provider value={dispatch}>
{children}
</UserDispatchContext.Provider>
</UserStateContext.Provider>
);
}
function useUserState() {
return React.useContext(UserStateContext);
}
function useUserDispatch() {
return React.useContext(UserDispatchContext);
}
function signOut(dispatch) {
dispatch({});
}
export { UserProvider, useUserState, useUserDispatch, loginUser, signOut };
The client code above will produce error "Hooks can only be called inside of the body of a function component".
So maybe I have to move line var dispatch = useUserDispatch()
upward to the component where request
is called, and pass dispatch
as props to request
.
I feel this is not right, no only request
is forced to care about some meaningless(to it) dispatch
, but also this dispatch
will spread everywhere a component needs to request
.
For class-based components, this.state
doesn't solve this problem either, but at least I can use mobx.
So are there some other ideal ways to solve this problem?
解决方案
Mobx 和 hooks 在实现上非常相似。两者都使用某种意义上的“全局”渲染上下文。React 将渲染上下文与组件渲染上下文联系起来,但 Mobx 将渲染上下文分开。因此,这意味着必须在组件渲染生命周期内创建挂钩(但有时可以在该上下文之外调用)。Mobx-react 将 Mobx 渲染生命周期与反应生命周期联系起来,当观察到的对象发生变化时触发反应重新渲染。所以 Mobx-react 将 React 渲染上下文嵌套在 Mobx 渲染上下文中。
React 在内部跟踪 hooks 的次数和在组件渲染周期内调用 hook 的顺序。另一方面,Mobx 使用代理包装任何“可观察”对象,让 Mobx 上下文知道在 Mobx“运行上下文”(autorun
本质上是调用)期间是否引用了它的任何属性。然后,当一个属性发生变化时,Mobx 知道什么“运行上下文”关心该属性,并重新运行这些上下文。这意味着您可以在任何可以访问可观察对象的地方更改其属性,而 Mobx 会对其做出反应。
对于 react 状态钩子,react 为状态对象提供了一个自定义的 setter 函数。然后 React 使用对该 setter 的调用来了解何时需要重新渲染组件。该setter可以在任何地方使用,甚至在 React 渲染之外,但您只能在渲染调用中创建该钩子,因为否则 react 无法告诉该钩子要绑定到哪个组件。创建一个钩子隐式地将它连接到当前渲染上下文,这就是为什么必须在渲染调用中创建钩子的原因:钩子构建器在渲染调用之外没有任何意义,因为它们无法知道它们连接到什么组件——但是一旦绑定到一个组件,那么它们就需要在任何地方都可用。事实上,onClick
像fetch
回调不会发生在渲染上下文中,尽管回调通常是在该上下文中创建的 - 动作回调发生在反应完成渲染之后(因为 javascript 是单线程的,所以渲染函数必须在其他任何事情发生之前完成)。
推荐阅读
- php - 在家谱 SQL/PHP 中查找共同祖先的概念
- javascript - Chrome 扩展:更改特定类的元素的呈现方式?
- javascript - axios 得到 404 因为 axios 模拟适配器
- c# - JWT 加密的密钥管理 (ASP.NET Core 5)
- powerbi - 无法让行标题在具有自定义主题的 Power BI 中更改颜色
- microsoft-graph-api - MsalUiRequiredException:没有帐户或登录提示传递给 AcquireTokenSilent 调用
- javascript - 不发送 httpResponse 时的 NestJs 异常处理
- java - '从 Corda Vault 获取未使用的总数'
- angular - 角。@输入变化检测性能
- c++ - 使用类向量来显示内容。Vector.size() 不在构造函数中时变为 0