Open subaru-hello opened 1 year ago
async/awaitを用いてdata fetchして返ってきたresponceをアプリ内のstateに入れたい時は、data fetchするサイクル内に入れる必要がある。
さもないと、期待する挙動ではなく、Promise
useEffect(() => {
// declare the async data fetching function
const fetchData = async () => {
// get the data from the api
const data = await fetch('https://yourapi.com');
// convert data to json
const json = await data.json();
return json;
}
// call the function
const result = fetchData()
// make sure to catch any error
.catch(console.error);;
// ❌ don't do this, it won't work as you expect!
setData(result);
}, [])
But
useEffect(() => {
// declare the async data fetching function
const fetchData = async () => {
// get the data from the api
const data = await fetch('https://yourapi.com');
// convert the data to json
const json = await response.json();
// set state with the result
setData(json);
}
// call the function
fetchData()
// make sure to catch any error
.catch(console.error);;
}, [])
data fetchingをする関数をuseEffectの外側で定義したい場合は、useCallbackを使う必要がある。 そうしないと、UIがレンダーされる度にdata fetchingをする関数が実行されてしまう。 同時に、useEffectは依存配列内でdata fetchingをする関数をバインドしているため、UIがレンダーされる度にuseEffectも実行されてしまう。
// declare the async data fetching function
const fetchData = useCallback(async () => {
const data = await fetch('https://yourapi.com');
setData(data);
}, [])
// the useEffect is only there to call `fetchData` at the right time
useEffect(() => {
fetchData()
// make sure to catch any error
.catch(console.error);;
}, [fetchData])
パラメーターが渡ってきた場合の挙動。 ユーザー詳細画面にuserID1が渡ってきた際に、data fetchingが2回走らないようにしたい。 結構簡単で、条件分岐を足してあげれば良い。 最初はtrueにしてある変数を、useEffectの終わりにfalseに変えるような記述にしておくと、paramに変更がない限り、Dataは2回セットされる事が無くなる。 便利
useEffect(() => {
let isSubscribed = true;
// declare the async data fetching function
const fetchData = async () => {
// get the data from the api
const data = await fetch(`https://yourapi.com?param=${param}`);
// convert the data to json
const json = await response.json();
// set state with the result if `isSubscribed` is true
if (isSubscribed) {
setData(json);
}
}
// call the function
fetchData()
// make sure to catch any error
.catch(console.error);;
// cancel any future `setData`
return () => isSubscribed = false;
}, [param])
https://devtrium.com/posts/async-functions-useeffect#note-on-fetching-data-inside-useeffect
useEffectが返却する型は、副作用を完全に無くすために、undefined又はfunctionでないといけない。 そのため、下記のように、useEffectに対してasyncを付けるとPromiseを返してしまうためNG。 Not
Promise文は関数宣言文を用意してから実行する必要がある。 But
参考
https://devtrium.com/posts/async-functions-useeffect