Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

useEffect内のdatafetchingに順序をつける #36

Open
subaru-hello opened this issue Jan 13, 2023 · 3 comments
Open

useEffect内のdatafetchingに順序をつける #36

subaru-hello opened this issue Jan 13, 2023 · 3 comments

Comments

@subaru-hello
Copy link
Owner

subaru-hello commented Jan 13, 2023

useEffectが返却する型は、副作用を完全に無くすために、undefined又はfunctionでないといけない。
そのため、下記のように、useEffectに対してasyncを付けるとPromiseを返してしまうためNG。
Not

useEffect(async () => {
  const data = await fetchData();
}, [fetchData])

Promise文は関数宣言文を用意してから実行する必要がある。
But

useEffect(() => {
  // declare the data fetching function
  const fetchData = async () => {
    const data = await fetch('https://yourapi.com');
  }

  // call the function
  fetchData()
    // make sure to catch any error
    .catch(console.error);
}, [])

参考

https://devtrium.com/posts/async-functions-useeffect

@subaru-hello
Copy link
Owner Author

subaru-hello commented Jan 13, 2023

async/awaitを用いてdata fetchして返ってきたresponceをアプリ内のstateに入れたい時は、data fetchするサイクル内に入れる必要がある。
さもないと、期待する挙動ではなく、Promiseがstateに入ってしまう。
Not

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);;
}, [])

@subaru-hello
Copy link
Owner Author

subaru-hello commented Jan 13, 2023

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])

https://devtrium.com/posts/dependency-arrays

@subaru-hello
Copy link
Owner Author

subaru-hello commented Jan 13, 2023

パラメーターが渡ってきた場合の挙動。
ユーザー詳細画面に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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant