在既不是 React 函数组件也不是自定义 React Hook 函数的函数中调用了 React Hook "useAxios"

React Hook "useAxios" is called in function that is neither a React function component nor a custom React Hook function

我创建了一个自定义 useAxios 挂钩来进行 api 调用。

我正尝试在我的登录组件中使用它,如下所示。

import { useContext, useState } from 'react';
import './login.scss';
import { useNavigate } from 'react-router-dom';
import { useAxios } from '../../api/use-axios';
import ApiConfig from '../../api/api-config';
import { AuthContext } from '../../context/AuthContext';

const LOGIN_AXIOS_CONFIG = ApiConfig.AUTH.LOGIN;

const Login = () => {
  const [loginError, setLoginError] = useState('');
  const [phone, setPhone] = useState('');
  const [password, setPassword] = useState('');

  const navigate = useNavigate();
  const { dispatch } = useContext(AuthContext);

  const handleLogin = (e) => {
    e.preventDefault();
    LOGIN_AXIOS_CONFIG.data = {
      phone,
      password,
    };
    const { response: loginData, error } = useAxios(LOGIN_AXIOS_CONFIG);
    if (error) {
      setLoginError(error);
    } 
    if (loginData) {
        dispatch({ type: 'LOGIN', payload: loginData });
        navigate('/');
    }
  };
  return (
    <div className="login">
      <div className="logo">
        <h1>LOGO</h1>
        <h3>LOGO DESCRIPTION</h3>
      </div>
      <form onSubmit={handleLogin}>
        <input type="number" placeholder="phone" onChange={(e) => setPhone(e.target.value)} />
        <input type="password" placeholder="password" onChange={(e) => setPassword(e.target.value)} />
        <button type="submit">Submit</button>
        {loginError && <span>{loginError}</span>}
      </form>
    </div>
  );
};

export default Login;

使用-axios.js

import { useState, useEffect } from 'react';
import axios from 'axios';

export const useAxios = (axiosParams) => {
  const [response, setResponse] = useState(undefined);
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(true);

  const fetchData = async (params) => {
    try {
      const result = await axios.request({
        ...params,
        method: params.method || 'GET',
        headers: {
          accept: 'application/json',
          authorization:
            'Bearer my-token',
        },
      });
      console.log(result.data);
      setResponse(result.data);
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchData(axiosParams);
  }, [axiosParams]); // execute once only

  return { response, error, loading };
};

反应是否看到 use 前缀并给出错误?

我该如何解决这个问题?

您需要对自定义挂钩稍作更改 useAxios,因为挂钩只能在组件主体中调用,不能有条件地调用。我向该挂钩添加了一个参数来处理 auto-fetch。在这种情况下,您不希望它自动触发提取,而是命令式的,所以只需 return 钩子中的提取器函数并命令式地使用它。顺便说一句,最好不要耦合钩子并创建两个单独的钩子,例如 useAxiosOnMountuseAxiosOnAction。为简单起见,我将在此处编辑您的 useAxios 挂钩:


const Login = () => {
  const [loginError, setLoginError] = useState('');
  const [phone, setPhone] = useState('');
  const [password, setPassword] = useState('');

  const navigate = useNavigate();
  const { dispatch } = useContext(AuthContext);

  const {fetch, loading, response, error} = useAxios(LOGIN_AXIOS_CONFIG, false)

  useEffect(() => {
   if (response) // do something
   if (error) // do something else
  },[response,error])

  const handleLogin = (e) => {
    e.preventDefault();
    fetch()
  };

  return (
    <div className="login">
      <div className="logo">
        <h1>LOGO</h1>
        <h3>LOGO DESCRIPTION</h3>
      </div>
      <form onSubmit={handleLogin}>
        <input type="number" placeholder="phone" onChange={(e) => setPhone(e.target.value)} />
        <input type="password" placeholder="password" onChange={(e) => setPassword(e.target.value)} />
        <button type="submit">Submit</button>
        {loginError && <span>{loginError}</span>}
      </form>
    </div>
  );
};

export default Login;

use-axios.js

export const useAxios = (axiosParams, isAuto) => {
  const [response, setResponse] = useState(undefined);
  const [error, setError] = useState('');
  const [loading, setLoading] = useState(true);

  const fetchData = async (params) => {
    try {
      const result = await axios.request({
        ...params,
        method: params.method || 'GET',
        headers: {
          accept: 'application/json',
          authorization:
            'Bearer my-token',
        },
      });
      console.log(result.data);
      setResponse(result.data);
    } catch (error) {
      setError(error);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    if (isAuto)
    fetchData(axiosParams);
  }, [axiosParams, isAuto]); // execute once only

  return { fetch: () => fetchData(axiosParams), response, error, loading };
};