如何执行内部包含反应钩子的函数

How to execute a function that contains a react hook inside

我正在使用 React 和 nodeJS 构建一个应用程序。我想进行 API 调用并在此函数内使用反应钩子从 Auth0 获取令牌以使用 API.

进行身份验证
async function CallApi(userId) {
  const { getTokenSilently } = useAuth0();
  const token = await getTokenSilently();
  try {
    const response = await fetch(process.env.API_URL + "users", {
      headers: {
        Authorization: `Bearer ${token}`,
        user_id: userId
      }
    });

    var result = JSON.stringify(await response.json());

  } catch (error) {
    console.error(error);
  }
  return result;
};

export default CallApi;

现在我想在另一个文件中调用这个函数:

async componentDidMount() {
    this.setState({ readError: null });
    try {
      var profile = await CallApi("own");
      this.setState({
        username: profile.username,
        email: profile.email
      })
    } catch (error) {
      this.setState({ readError: error.message });
    }
  }

现在,如果我想打开这个网站,我会收到错误 Unhandled Rejection (Error): Invalid hook call. Hooks can only be called inside of the body of a function component.

我做错了什么,我怎样才能从这个钩子中获取令牌?

https://reactjs.org/warnings/invalid-hook-call-warning.html

为避免混淆,不支持在其他情况下调用Hooks:

不要在 class 个组件中调用 Hook。

不要调用事件处理程序。

不要在传递给 useMemo、useReducer 或 useEffect 的函数内部调用 Hooks。

因为使用的是钩子调用 useAuth0==> 你需要在功能组件的主体或有前缀的客户钩子中调用它 use ==> 你CallApi 不是钩子 ==> 你得到了错误。

  1. 创建 useCallApi 挂钩。

 
function useCallApi(userId) {
  const [result, setResult] = c()
  const { getTokenSilently } = useAuth0();
  const [loading, setLoading] = useState(false)
  const [error, setError] = useState(null)
  const fetchResult = useCallback( async(userId) =>{
      const token = await getTokenSilently();
      try {
        setLoading(true)
        const response = await fetch(process.env.API_URL + "users", {
          headers: {
            Authorization: `Bearer ${token}`,
            user_id: userId
          }
        });
        setLoading(false)
        var result = JSON.stringify(await response.json());
        setResult(result)
      } catch (error) {
        setLoading(false)
        setError(error)
        console.error(error);
      }
    },[userId])

  useEffect(() =>{
    if(userId){
       fetchResult()
    }
  },[userId])
  
  return {userInfor: result, loading, error,fetchResult};
};

export default useCallApi;

  • 现在我想在另一个文件中调用这个函数,但是你需要 将现有组件转换为功能组件并使用 useCallApi挂钩。

  • 如果你在声明 useCallAPi 时传递一个字符串,像这样 useCallAPI("own"),它将直接调用 api。

  • 您还可以 const {result, fetchResult} = useCallAPi("own") 并在任何您想要获取结果的地方调用 fetchResult("own")

//other import
import {useCallAPi} from "path_to/useCallApi.js"
// you need to convert your class compoenent to this compoenent
function AFunctionalComponent(userId) {
  const [readError, setReadError] = useState(null)
  // result include username and email walready
  const {result} = useCallAPi("own")


  return(
    // your ui render herer
  )
};

更新:如果你想在功能组件中基于 result 设置本地状态,你可以试试这个

//other import
import {useCallAPi} from "path_to/useCallApi.js"
// you need to convert your class compoenent to this compoenent
function AFunctionalComponent(userId) {
  const [readError, setReadError] = useState(null)
  const [useInfo, setUserInfo] = useState(null)
  // result include username and email walready
  const {result} = useCallAPi("own")

  useEffect(() =>{
    if(result){
       setUserInfo({
          username: result. username,
          email: result.email
       })
    }
  },[result])

  return(
    // your ui render herer
  )
};