reactjs React应用程序中的可重用API调用方法?

neskvpey  于 2023-03-17  发布在  React
关注(0)|答案(3)|浏览(115)

我试图创建一个可重用的方法或功能组件,以便在HTTP方法之间不重复相同的逻辑。为此,我创建了以下方法:

服务.js

import axios from "./axios";

// I cannot use state:
// const [jwt, setJwt] = useState();

const AUTH_TOKEN = localStorage.getItem("tokenKey");

const config = {
  headers: {
    Accept: "application/json",
    Authorization: `Bearer ${AUTH_TOKEN}`
  },
};

export const getWithAuth = (url) => {
  const request = axios.get(url, config);
  return request.then((response) => response.data);
};

export const postWithAuth = (url, body) => {
  const request = axios.post(url, body, config);
  return request.then((response) => response.data);
};

但是每当我需要使用这个服务中的任何组件或状态时,我都会遇到问题。因此,我想将这个类更改为更好的格式,可能我需要将方法转换为钩子,或者我需要创建一个功能组件并将方法保留在其中。由于我是初学者,无法找到正确的用法示例,您能告诉我一个正确的用法示例吗?

wbrvyc0a

wbrvyc0a1#

你可以创建自己的自定义钩子。下面是一个例子,说明了一种方法:

// localStorage is prohibited in snippets for security reasons
// const AUTH_TOKEN = localStorage.getItem("tokenKey")
const AUTH_TOKEN = '';

const config = {
  headers: {
    Accept: "application/json",
    Authorization: `Bearer ${AUTH_TOKEN}`
  },
};

// Axios lets you set defaults
// e.g., axios.defaults.headers.common['Authorization'] = `Bearer ${AUTH_TOKEN}`;
axios.defaults.baseURL = 'https://pokeapi.co/api/v2/pokemon/'

// Custom hook names always start with use: 
function useAxios({ url, method, body = null, withHeaders = false }) {
  const [response, setResponse] = React.useState(null);
  const [error, setError] = React.useState('');
  const [loading, setLoading] = React.useState(true);

  const requestData = () => {
    setLoading(true)
    setError('')
    const headers = withHeaders ? config.headers : null;
    axios[method](url, headers, body)
      .then((res) => {
          setResponse(res.data);
      })
      .catch(setError)
      .finally(() => setLoading(false));
  };

  // The custom hook is rerendered with your component
  // changes in props will cause the request to be made
  React.useEffect(() => {
      requestData();
  }, [method, url, body, withHeaders]);

  // Return an object with the response, error and loading state
  return { response, error, loading };
};

function App(){
  const [data, setData] = React.useState({});

  // You can then use your custom hook inside a functional component,
  // passing it the { method, url, body, withHeaders } argument
  // and destructure the response, loading, and error state
  // return values
  const { response, loading, error } = useAxios({
    method: 'get',
    url: '14', /* appended to the end of the baseURL config */
    withHeaders: true /* defaulted to false in the example hook */
  });
  
  React.useEffect(()=>{
    // if there's data in the response put it in 
    // the component state so that it renders the data
    if (response !== null) setData(response)
  }, [response])

  if (loading) return <div>Loading...</div>

  return (
    <pre>{JSON.stringify(data)}</pre>
  )
}

ReactDOM.createRoot(document.getElementById("root")).render(<App />);
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>
<div id="root"></div>
rggaifut

rggaifut2#

我推荐使用ReactQuery。这将帮助你以一种很好的方式组织你的API调用,并将它们暴露为钩子。 checkout https://tanstack.com/query/latest/docs/react/overview。祝你好运!

tkclm6bt

tkclm6bt3#

你是不是想避免使用async/await?我不知道你遇到了什么问题,但是也许你可以试试这样的方法?

const getWithAuth = async (url) => {
    await axios.get(url, {params: {key: value}}).then((response) => {
      return response.data
    }
  })
}

另外,你能使用fetch吗?我最终从我的项目中删除了axios,发现像你这样的可重用调用的实现更简单。

相关问题