是否可以在功能组件之外使用 React Hooks,或者我必须使用 mobx 或 redux?

新手上路,请多包涵

我是 React 的新手,当我阅读文档时,我发现有两种方法可以实现 React 组件,基于功能的和基于类的。我知道在 React 16.8 之前无法在功能组件中管理状态,但在那之后就有了 React Hooks。

问题是,React Hooks 似乎有一个限制,它们只能在功能组件内部使用。以server-client为例,收到401时需要改变一个 isAuthenticated 状态。

 //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 };

上面的客户端代码会产生错误“Hooks can only be called inside of a function component”。 So maybe I have to move line var dispatch = useUserDispatch() to the component where request is called, and pass dispatch as props to request .我觉得这是不对的,不仅 request 被迫关心一些无意义的(对它而言) dispatch ,还有这个 dispatch spread everywhere component-需要 request

对于基于类的组件, this.state 也没有解决这个问题,但至少我可以使用mobx。

那么还有其他一些理想的方法来解决这个问题吗?

原文由 apporc 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 334
2 个回答

是的,你必须使用 Redux 或 MobX 来解决这个问题。您必须在 Redux 或 MobX 的全局状态中维护 isAuthenticated 状态。然后做一个可以命名为 toggleAuthState 的动作,并将它传递给子组件并从那里切换状态。

您也可以在这种情况下使用功能组件。基于类的组件不是强制使用 MobX 或 Redux 的。如果您将 HOC 维护为 Container 那么您可以将操作和状态传递给孩子。

我展示了一个使用容器作为 HOC 的例子:

 // Container
import React from "react"
import * as actions from "../actions"
import ChildComponent from "../components/ChildComponent"
import { connect } from "react-redux"
import { bindActionCreators } from "redux"

const Container = props => <ChildComponent { ...props } />

const mapStateToProps = state => ({ ...state })

const mapDispatchToProps = dispatch => bindActionCreators(actions, dispatch)

export default connect(mapStateToProps, mapDispatchToProps)(Container)

然后在 ChildComponent 你可以随时使用你的状态和调度动作。

原文由 bonnopc 发布,翻译遵循 CC BY-SA 4.0 许可协议

我也是这个时候过来的。长话短说,如果您想自己手动完成所有工作,您需要将 Redux 和 Thunk 与 Async Logic 一起使用,如以下链接 [1] 中的示例详细描述。

[1] https://redux.js.org/tutorials/essentials/part-5-async-logic

还有另一种解决方案提供 开箱即用的异步 API 体验(可以与 OpenAPI 和 GraphQL 一起工作,处理请求,提供生命周期缓存等)包装来自 [1] 的内容及其称为 RTK 查询[2]。

[2] https://redux-toolkit.js.org/rtk-query/overview

下图直观地解释了 [1] 过程……但我认为 RTK 查询[2] 将所有内容都放在一个地方,可能是更好的解决方案。有一个快速入门指南 [3]。我会试一下 :-)

[3] https://redux-toolkit.js.org/tutorials/rtk-query/

原文由 CeDeROM 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题