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

问题描述 投票:0回答:3

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

问题是,React Hook似乎有一个限制,它们只能在功能组件内部使用。以服务器-客户端为例,在接收到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 };

上面的客户端代码将产生错误“只能在函数组件的主体内部调用挂钩”。因此,也许我必须将var dispatch = useUserDispatch()行向上移至调用request的组件,然后将dispatch作为道具传递给request。我觉得这是不对的,不仅request被迫关心一些毫无意义的dispatch,而且这个dispatch也会散布到需要request的所有组件上。

对于基于类的组件,this.state也不能解决此问题,但是至少我可以使用mobx。

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

javascript reactjs react-hooks mobx mobx-react
3个回答
0
投票

挂钩是基于类的组件的替代品,您应在项目中选择一个并坚持使用,请勿混淆。有一些创建钩子的动机,正如在文档hook motivation中更好地指出的那样。

您可以分开创建钩子函数,但是它们应由组件consumed

所用。就像将HOC(高阶组件)与基于类的组件一起使用。
const myHook = () => {
  [foo, setFoo] = useState('john')
  // use effect for example if you need to run something at state updates
  useEffect(() => { 
    // do something on foo changes
  }, [foo])

  return [foo, setFoo] // returning state and setState you can use them by your component
}

现在您有了一个可重复使用的钩子,可以在组件中使用它了:

const myComponent = (props) => {
  [foo, setFoo] = myHook()

  const handleFoo = () => { 
    // some logic
    setFoo(someValue)
  }      
  return (
    <div>
      <span>{foo}<span>
      <button onClick={handleFoo}>click</button>
    </div>
  )
}

obs:您现在应该避免将变量声明为var,大多数情况下都选择const,并且如果它是需要更新使用let的值变量(例如数字)。


0
投票

是,您必须使用Redux或MobX来解决此问题。您必须在Redux或MobX的全局状态下保持isAuthenticated状态。然后执行一个可以命名为toggleAuthState的动作,并将“ pass”传递给子组件,然后从那里切换状态。


0
投票

创建钩子时,必须参考Rules of Hooks

© www.soinside.com 2019 - 2024. All rights reserved.