LoginSignup
11
14

More than 5 years have passed since last update.

React.useEffectで非同期処理をする場合に無駄に再レンダリングしないための手法2つ

Posted at

はじめに

React hooksのuseEffectで非同期処理を書くことができます。この時、コンポーネントのstateを変更する場合がしばしばありますが、場合によっては複数回レンダリングすることがあります。

複数回レンダリングする例

import React, { useEffect, useState } from 'react';

const MyComponent = () => {
  const [greeting, setGreeting] = useState('Hello');
  const [name, setName] = useState('World');
  useEffect(() => {
    setTimeout(() => {
      setGreeting('Hi');
      setName('React');
    }, 1000);
  }, []);
  return (
    <div>{greeting}{' '}{name}</div>
  );
};

現状だと、setTimeoutのコールバックでsetGreeting, setNameでそれぞれレンダリングされます。これが問題ないケースもあるかと思いますが、改善したいケースもあるかもしれません。

解決策1

useReducerを使うことで解決できます。

import React, { useEffect, useReducer } from 'react';

const initialState = {
  greeting: 'Hello',
  name: 'World',
};

const reducer = (state, action) => ({
  greeting: action.greeting,
  name: action.name,
});

const MyComponent = () => {
  const [state, dispatch] = useReducer(reducer, initialState);
  useEffect(() => {
    setTimeout(() => {
      dispatch({
        greeting: 'Hi',
        name: 'React',
      });
    }, 1000);
  }, []);
  return (
    <div>{greeting}{' '}{name}</div>
  );
};

解決策2

unstalbed_batchedUpdatesを使うことでも解決できます。Reactの内部的にはイベントハンドラで使われているものです。

import React, {
  useEffect,
  useState,
  unstable_batchedUpdates as batchedUpdates,
} from 'react';

const MyComponent = () => {
  const [greeting, setGreeting] = useState('Hello');
  const [name, setName] = useState('World');
  useEffect(() => {
    setTimeout(() => {
      batchedUpdates(() => {
        setGreeting('Hi');
        setName('React');
      });
    }, 1000);
  }, []);
  return (
    <div>{greeting}{' '}{name}</div>
  );
};

APIとしてはunstableなのでお気をつけください。

おわりに

個人的にはできるだけuseStateを使ってシンプルに組み立てたいですが、場合によってはuseReducerを使う方が問題が起こりにくいため活用するのが良いとは思います。その場合は、カスタムフックにしてロジックを切り分けた方が良いかもしれません。

11
14
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
11
14