3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

useState更新タイミング/useEffect初回レンダリング、非同期処理

Last updated at Posted at 2022-01-28

たぶん Vue から React に来た人ははまるんじゃないかポイント

useState

初めて見ると変わった書き方だが、ただ状態管理してくれるもの
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }
    return <div onClick={up}>{data}</div>;
};

クリックしたら1づつ上がる関数である

更新タイミング

ここで私は躓いた 例えば、クリックされプラス1されたとき、この数字をバックエンドに送りたい時なんかを考える
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
        console.log(data)
    }
    return <div onClick={up}>{data}</div>;
};

1 回クリックしたときのコンソールは0
2 回目は1

おかしいぞ、1ずつずれている

どうやら、useState の data が更新されるのは up 関数が終了後らしい

それを踏まえて、更新時に何か処理したいときには、こう書けばいいらしい

const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }

    useEffect(() => {
        console.log(data)
    //data更新時の処理
    }, [data])

    return <div onClick={up}>{data}</div>;
};

useEffect

非同期処理

useEffect内で非同期処理をする場合はこうかく
const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }

    useEffect(() => {
        const fetch = async () => {
           //非同期処理
            await axios.get("API")
        }
        fetch()
    }, [data])

    return <div onClick={up}>{data}</div>;
};

これでデータが更新されたときに非同期処理ができる

    useEffect(async() => {
        await axios.get("API");
    },[data])

こう書くとエラーが出てしまう
理由はコールバックの中に async 関数や Promise はいれられないから

初回レンダリング

useEffect の第二引数に[]を指定するとマウント時にのみレンダリングされる

先ほどのプログラムを例に見てみよう

const Qiita = () => {
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
    }

    useEffect(() => {
        const fetch = async () => {
            console.log("初回レンダリング")
            await axios.get("API")
        }
        fetch()
    }, [data])

    return <div onClick={up}>{data}</div>;
};

こちら側の意図としてはクリックされて up 関数実行され、data が更新した時に API を取得してほしい

だが実際は、data はマウント時にも更新されるので、クリックする前に get の処理は一度実行されてしまう

初回レンダリング時の useEffect の実行を防ぐにはこうかく

const Qiita = () => {
    const renderFlgRef = useRef(false);
    const [data, setData] = useState(0)
    const up = () => {
        setData((data) => data + 1)
        console.log(data)
    }

    useEffect(() => {
        if (renderFlgRef.current) {
          const fetch = async () => {
            console.log("クリック時に実行");
            //await axios.get("API")
          };
          fetch();
        } else {
          renderFlgRef.current = true;
        }
    }, [data])

    return <div onClick={up}>{data}</div>;
};

初回レンダリングでフラグをたたせて、二回目以降は条件分岐してやればいい

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?