react-dom.development.js:4379 Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.このエラーはReactのレンダリング時にsetStateが呼ばれて無限ループに陥った時にでるエラーです。
このエラー文を翻訳すると以下のようになります。
最大更新数を超えました。 これは、コンポーネントがcomponentWillUpdateまたはcomponentDidUpdate内でsetStateを繰り返し呼び出す場合に発生する可能性があります。 Reactは、ネストされた更新の数を制限して無限ループを防ぎます。
このエラーを解消するには無限ループとなっているコードを変更する必要があります。
今回はこのエラーが出たときの解決方法と原因をご紹介します。
解決方法はsetStateを呼び出さいようにすること
クリックイベントなどのイベントハンドラでsetStateを含む関数を実行しないようにすると無限ループを防ぐことができます。
16行目のようにonClick={this.handleOpen}と書いて関数にカッコをつけないか、
または20行目のようにonClick={() => this.handleOpen(false)}と書いて、イベントハンドラにアロー関数として定義すると無限ループを解消できます。
class OpenComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
};
this.handleOpen = this.handleOpen.bind(this);
}
handleOpen(is_open=true) {
this.setState({ open: is_open);
}
render() {
return (
<div>
<button onClick={this.handleOpen}>
OPEN
</button>
<button onClick={() => this.handleOpen(false)}>
CLOSE
</button>
<div>
)
}
}原因はsetStateを呼び出すと再レンダリングされるから
無限ループになる原因はクリックイベントなどに定義したsetStateを含む関数がレンダリング時に発火することです。
setStateは呼ばれると再レンダリングします。
https://ja.reactjs.org/docs/state-and-lifecycle.html
setState()が呼び出されたおかげで、React は state が変わったということが分かるので、render()メソッドを再度呼び出して、画面上に何を表示すべきかを知ります。
具体的に無限サイクルに陥るサイクルは以下のとおりです。
render を実行→this.handleOpen を実行→setState を実行→再度 render を実行→繰り返し
以下のコードではコンポーネントがレンダリングされるたびにクリックイベントに定義したthis.handleState(true)が発火します。
class OpenComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
};
this.handleOpen = this.handleOpen.bind(this);
}
handleOpen(is_open=true) {
this.setState({ open: is_open);
}
render() {
return (
<div>
<button onClick={this.handleOpen()}> // setStateを呼び出すので無限ループ
OPEN
</button>
<button onClick={this.handleOpen(false)}> // setStateを呼び出すので無限ループ
CLOSE
</button>
<div>
)
}
}まとめ
render内でsetStateを使っていたり、setStateを呼び出している関数がないか確認してください。
setStateを呼び出していたら次のように変更してください。
- 関数名を渡す(関数名にカッコを付けない)
- アロー関数を使用する
Reactのレンダリング時にsetStateが呼ばれないようになり無限ループのエラーが解消されます。
class OpenComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
};
this.handleOpen = this.handleOpen.bind(this);
}
handleOpen(is_open=true) {
this.setState({ open: is_open);
}
render() {
return (
<div>
// <button onClick={this.handleOpen()}> // setStateを呼び出すので無限ループ
<button onClick={this.handleOpen}> // 関数名を渡す(関数名にカッコを付けない)
OPEN
</button>
// <button onClick={this.handleOpen(false)}> // setStateを呼び出すので無限ループ
<button onClick={() => this.handleOpen(false)}> // アロー関数を使用する
CLOSE
</button>
<div>
)
}
}コンポネントに関数を渡す方法はこちらが参考になります。
https://ja.reactjs.org/docs/faq-functions.html
下記に参考書をまとめておきます。

JavaScriptを基礎からしっかり学びたい方におすすめ!

JavaScriptを基礎から応用までガッツリ学びたい方におすすめ!

Reactの概念や仕組みを把握し、開発で使えるReactを学びたい方にオススメ!









コメント