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を学びたい方にオススメ!
コメント