2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

React useEffect内での同期的setStateエラー

2
Last updated at Posted at 2026-01-19

はじめに

みなさん2026年は調子はどうですか??
僕は正直、たるんでいると感じております。このままだとヤバいので今日からまた
業務とは別に勉強をし始めました!!
本日は勉強して詰まったエラーについてまとめて見たいと思います
それではどうぞ

この記事で分かること

この記事では、ReactのuseEffect内で同期的にsetStateを呼び出すことで発生するエラーについて説明します。

  • エラーの内容: useEffect内での同期的なsetState呼び出しが原因で発生する「cascading renders」エラー
  • エラーの原因:
    • カスケードレンダリングによるパフォーマンス問題
    • useEffectの設計意図(外部システムとの同期)に反する使用
  • 解決方法:
    • 初期状態はuseStateの初期値で設定する
    • useEffect内では非同期処理の完了後にのみ状態を更新する
  • 実装例: ローディング状態の管理を例に、修正前後のコードと推奨パターンを紹介

1. エラーコードとエラー場所

エラーメッセージ

Error: Calling setState synchronously within an effect can trigger cascading renders

Effects are intended to synchronize state between React and external systems such as manually updating the DOM, state management libraries, or other platform APIs. In general, the body of an effect should do one or both of the following:
* Update external systems with the latest state from React.
* Subscribe for updates from some external system, calling setState in a callback function when external state changes.

Calling setState synchronously within an effect body causes cascading renders that can hurt performance, and is not recommended.

エラー発生箇所

// src/index.jsx:12-13
useEffect(() => {
  setIsLoading(true);  // ← ここでエラー発生
  const getRecords = async () => {
    // ...
  };
  getRecords();
}, []);

2. エラー対応(正確にエラー解除できた方法)

修正前

const [isLoading, setIsLoading] = useState(false);

useEffect(() => {
  setIsLoading(true);  // ❌ 同期的なsetState呼び出し
  const getRecords = async () => {
    const { data, error } = await supabase.from("study-record").select();
    if (error) {
      console.error(error);
    } else {
      setRecords(data);
    }
    setIsLoading(false);
  };
  getRecords();
}, []);

修正後

const [isLoading, setIsLoading] = useState(true);  // ✅ 初期値をtrueに変更

useEffect(() => {
  // setIsLoading(true); を削除
  const getRecords = async () => {
    const { data, error } = await supabase.from("study-record").select();
    if (error) {
      console.error(error);
    } else {
      setRecords(data);
    }
    setIsLoading(false);  // ✅ 非同期処理完了後にのみ状態更新
  };
  getRecords();
}, []);

変更点

  1. useState(false)useState(true) に変更(初期状態をローディング状態に設定)
  2. useEffect内のsetIsLoading(true)を削除

3. 根本原因(コード例)

問題の原因

ReactはuseEffect内での同期的なsetStateを推奨していません。理由は以下の通りです:

1. カスケードレンダリングの問題

useEffect実行中に同期的にsetStateを呼ぶと、エフェクト実行中に再レンダリングが発生し、パフォーマンスに影響を与えます。

2. useEffectの設計意図

useEffectは外部システム(API、DOM操作など)との同期が目的であり、内部状態の初期化には適していません。

3. 推奨パターン

  • 初期状態はuseStateの初期値で設定する
  • useEffectでは非同期処理の完了後にのみ状態を更新する

悪い例(エラーが発生するコード)

function App() {
  const [isLoading, setIsLoading] = useState(false);
  
  useEffect(() => {
    setIsLoading(true);  // ❌ 同期的なsetState
    fetchData().then(() => {
      setIsLoading(false);
    });
  }, []);
}

良い例(推奨パターン)

パターン1: 初期値を設定する方法

function App() {
  const [isLoading, setIsLoading] = useState(true);  // ✅ 初期値で設定
  
  useEffect(() => {
    fetchData().then(() => {
      setIsLoading(false);  // ✅ 非同期処理完了後に更新
    });
  }, []);
}

パターン2: 非同期関数を使う方法

function App() {
  const [isLoading, setIsLoading] = useState(true);
  
  useEffect(() => {
    const fetchData = async () => {
      const data = await api.getData();
      setRecords(data);
      setIsLoading(false);  // ✅ 非同期処理完了後に更新
    };
    fetchData();
  }, []);
}

まとめ

  • useEffect内では同期的なsetStateを避ける
  • ✅ 初期状態はuseStateの初期値で設定する
  • useEffect内では非同期処理の完了後にのみ状態を更新する

この修正により、エラーは解消され、Reactの推奨パターンに沿った実装になります。

おわりに

やっぱり、AIに頼ってばかりではだめですね!!
業務はどうしても、速度を求められるのでついclaude君に任せがちです。
修正コードについて理解をするためまたclaude君を使い理解を深めていく…
そしてその場では分かった!ってなるけど、後日また同じことを…この繰り返し
本当の意味でclaude君の実装をレビューできるエンジニアなろうと思った今日このごろです!!

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?