经过前面几天的介绍,我们认识了许多常使用的 hooks,不过除了那些 hooks 之外,我们也可以将一些常用的共同程序逻辑抽取出来写一个函式,这就是 Custom Hook。
在了解 Custom Hook 後,我们来实做一个 Custom Hook,这个 hook 是一个用来呼叫 Api 并进行一些处理的 Custom Hook,名字就叫 useAxios。
2022/1/26 更新 注: 这里只是示范如果做一个 Custom hook,在呼叫 api 还有其他的做法,例如 redux dispatch async action + middleware,读者可以自行依照状况判断使用~
在 codesandbox 新增一个档案 useAxios,引入 axios 套件後,我们要使用 JSONplaceholder 的 api 作为 Base URL,等这个 hook 完成後会使用它来呼叫 JSONplaceholder 的 api。
在 useAxios 档案我们宣告一个函式 useAxios,在做呼叫 api 时我们也会需要对一些像是呼叫 api 的载入时间和错误讯息做处理,所以建立两个 state: isLoading 和 error,并且建立一个发出请求的函式 sendRequest,在这个函式内会对呼叫的 api 做处理,最後回传一个包含 isLoading、error 和 sendRequest 的物件。
import { useState, useCallback } from "react";
import axios from "axios";
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com";
const useAxios = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const sendRequest = useCallback(() => {}, []);
return {
isLoading,
error,
sendRequest,
};
};
export default useAxios;
在 sendRequest 中,我们会传入两个参数 requestConfig 和 applyData,因为在呼叫每只 api 的路径、http 方法和其他参数都不太一样,所以透过 requestConfig 可以将这些资讯带入到 sendRequest 里面,处理完後透过 callback function 也就是第二个参数 applyData 将呼叫 api 的结果回传。
完成後的程序码如下:
import { useState, useCallback } from 'react';
import axios from 'axios';
axios.defaults.baseURL = "https://jsonplaceholder.typicode.com";
const useAxios = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
const sendRequest = useCallback(async (requestConfig, applyData) => {
setIsLoading(true);
setError(null);
let res;
try {
res = await axios({
url: requestConfig.url,
method: requestConfig.method ? requestConfig.method : 'GET',
headers: requestConfig.headers ? requestConfig.headers : {},
data: requestConfig.data ? requestConfig.data : null,
});
} catch (error) {
setError(error.message || 'Something went wrong!');
} finally {
if (res) {
applyData(res.data);
}
setIsLoading(false);
}
}, []);
return {
isLoading,
error,
sendRequest,
};
};
export default useAxios;
在 App 元件中呼叫几支 JSONplaceholder 的 api。
import { useEffect, useState } from "react";
import useAxios from "./useAxios";
export default function App() {
const [data, setData] = useState([]);
const { isLoading, error, sendRequest: fetchData } = useAxios();
const { sendRequest: createData } = useAxios();
useEffect(() => {
fetchData({ url: "/posts" }, (res) => {
console.log(res);
setData(res);
});
}, []);
const clickNewData = () => {
createData(
{
url: "/posts",
method: "POST",
data: {
// id 没加是因为 JSONPlaceholder 只做假新增不会更新到资料库,所以 JSONPlaceholder 会自动产生一个假的 id
userId: 10,
title: "新增的物件",
body: "example"
}
},
(res) => console.log(res)
);
};
if (isLoading) return <h1>Loading...</h1>;
if (error) return <h1>{error}</h1>;
return (
<>
<ul>
{data.map((item) => (
<li key={item.id}>
<p>{item.title}</p>
</li>
))}
</ul>
<button onClick={clickNewData}>新增</button>
</>
);
}
这次的实作程序码在以下连结,另外附上 JSONplaceholder 的官网连结:
>>: [前端暴龙机,Vue2.x 进化 Vue3 ] Day15.组件介绍
使用gMSA作为Sql Server的服务帐号 有时候为了让管理跨server的资源更方便,服务就需...
前言 延续着上篇的介绍,这篇要来介绍visualVM的Sampler页签 Sampler 这边我延续...
工程师太师了: 第10话 杂记: 前阵子朋友传了一个社团给我, 里面大致是一个武林盟主的设计, 想要...
终於拿到手的Raspberry Pi Compute module 4 参考 官网 (确保电脑没有连...
天亮了 昨晚是平安夜 关於迷雾森林故事 习惯 洛神:8号玩家请继续发言 8号: 我的视角,我觉得我的...