大家好,我是奶綠
最近在研究 Next.js 13,發現官方的範例使用到了一個新的 React.use 函式,深入追下去後,發現這是 React 下一版將加入的新 hook,他可以讓我們用更少的程式碼來 fetch Data。
因為新版還沒發佈,所以先需要手動將 React 升級到 18.3.xxxx 版。
先來看目前怎麼使用 React 來 fetch data。
import React from "react";
export default function Example() {
const [data, setData] = React.useState([]);
const [isLoading, setLoading] = React.useState(true);
React.useEffect(() => {
fetch("someUrl")
.then((res) => res.json())
.then(setData)
.finally(() => {
setLoading(false);
});
}, []);
return (
<section data-name="Example1">
{isLoading && <div>LOADING</div>}
<ul>
{data.map((d) => {
return <li key={d.id}>{d.text}</li>;
})}
</ul>
</section>
);
}
二個 state,一個記錄結果,一個用來判斷是否在 loading,再搭配 useEffect 時,呼叫 API。
React.use
來看看新的 React.use 是怎麼實作的。
import React from "react";
const fetchData = () => {
return fetch("someUrl").then((res) => res.json());
};
const promiseFetchData = fetchData();
const TodoData = () => {
// React.use
// const data = React.use(fetchData()); // !!! Warning 這樣會無限 loop
const data = React.use(promiseFetchData);
return (
<section data-name="TodoData">
<ul>
{data.map((d) => {
return <li key={d.id}>{d.text}</li>;
})}
</ul>
</section>
);
};
export default function Example() {
return (
<section data-name="Example2">
<React.Suspense fallback={<div>LOADING</div>}>
<TodoData />
</React.Suspense>
</section>
);
}
直接在 Component 裡使用 React.use(這裡放Promise 物件),這裡要注意喔,不能直接放函式
const data = React.use(fetchData()); // !!! Warning 這樣會無限 loop
// 因為 fetchData 完成後,該 Component 又會 rerender,然以後又呼叫一次 fetchData
// 又 rerender。
// 改成這樣即可
const promiseFetchData = fetchData();
const data = React.use(promiseFetchData);
要知道是否在 loading 的話,只需要在父元件使用 React.Suspense 即可。
過去是 Component 先 mounted 後,才打 API。
而使用 React.use 則是先打 API,才建立 Component。
是不是使用上變的很簡單呀,當然如果 fetchData 要傳參數的話,需要再包裝一下。
附上原始碼,祝大家