質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
onclick

onclickとはユーザーのクリック処理を指します。これは"onmousedown"(押下)と"onmouseup"(押上)の二つの事象の組み合わせです

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

Q&A

解決済

1回答

2304閲覧

ステートの更新によってイベントが発火してしまう

kimch

総合スコア8

onclick

onclickとはユーザーのクリック処理を指します。これは"onmousedown"(押下)と"onmouseup"(押上)の二つの事象の組み合わせです

イベントハンドラ

マウスのクリックなどの特定の事象(イベント)が発生した時に実行される処理のことをイベントハンドラと呼びます。

React.js

Reactは、アプリケーションのインターフェースを構築するためのオープンソースJavaScriptライブラリです。

0グッド

0クリップ

投稿2021/06/15 08:00

編集2021/06/15 08:30

#実現したいこと
Reactでtodoアプリを開発しているのですが、レンダリングのエラーが解決できず困っています。
皆様のお力をお借りしたく、質問させていただきます。
よろしくお願い致します。

#困っていること
再レンダリングでのループが起きてしまう。

InputTodo.jsxにて、inputタグとtextAreaタグ内でoncChangeを使用し、ブラウザ上にて入力した文字を入力する度にstate(InputTodo.jsx内で定義したstate)を更新している。
InputTodo.jsxに記述しているButtonタグ内でonClick={onCLickAdd(引数)}と記述して、親コンポーネントのonClickAdd関数を呼び出している。

#エラーコード
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:App.jsx import React,{useState} from "react"; import "./styles.css" import { Header }from './components/Header'; import { InputTodo }from './components/InputTodo'; import { IncompleteTodos } from './components/IncompleteTodos'; import { CompleteTodos } from './components/CompleteTodos'; function App() { const [todoContents, setTodoContents] = useState({title:"",text:"",limit:""}); const [incompleteTodos, setIncompleteTodos] = useState([{title:"",text:"",limit:""}]); const [completeTodos, setCompleteTodos] = useState([{title:"",text:"",limit:""}]); const onClickAdd = ( Title, Text, Limit)=>{ setIncompleteTodos(incompleteTodos.concat([{title:"Title",text:"Text",limit:"Limit"}])); }; return ( <> <Header /> {incompleteTodos.length >= 5 &&(<p style={{color:"red"}}>登録できるのは5個までです。</p>) } <InputTodo onClickAdd={onClickAdd} disabled={incompleteTodos.length > 5} /> <IncompleteTodos incompleteTodos={incompleteTodos} onClickComplete={onClickComplete} onClickDelete={onClickDelete} /> export default App;
react:InputTodo.jsx import React from 'react'; import { useState } from 'react'; import styled from 'styled-components'; import { Button, ButtonGroup } from "@chakra-ui/react" export const InputTodo =(props)=>{ const { onClickAdd, disabled} = props; const [todoTitle,setTodoTitle]= useState(""); const [todoText,setTodoText]= useState(""); const [todoLimit,setTodoLimit]= useState(""); const onChangeTitleValue = (e)=>setTodoTitle(e.target.value); const onChangeTextValue = (e)=>setTodoText(e.target.value); const onChangeLimitValue = (e)=>setTodoLimit(e.target.value); return( <> <INputBlock> <INputArea> <TItle>入力してください</TItle> <INputTag disabled={disabled} placeholder="titleを入力してください" value={todoTitle} onChange={onChangeTitleValue}></INputTag> </INputArea> <INputArea> <TExtArea disabled={disabled} placeholder="todoを入力してください" value={todoText} onChange={onChangeTextValue}></TExtArea> </INputArea> <INputArea> <INputTag disabled={disabled} placeholder="limitを入力してください" value={todoLimit} onChange={onChangeLimitValue}></INputTag> <BUtton disabled={disabled} onClick={onClickAdd(todoTitle,todoText,todoLimit)} >追加</BUtton> </INputArea> </INputBlock> </> ) }; const INputBlock = styled.div` background-color: rgb(202, 211, 39); width: 80%; border-radius: 20px; padding-bottom:10px; ` const INputArea = styled.div` margin: 20px; ` const TItle = styled.p` text-align: center; font-size: 25px; font-weight: bold; color: #666; ` const INputTag = styled.input` border-radius: 20px; border: none; padding: 6px 20px; ` const TExtArea = styled.textarea` border-radius: 20px; border: none; height: 80px; width: 80%; padding: 20px 20px; ` const BUtton = styled.button` border-radius: 20px; border: none; margin: 3px 5px 6px 3px; spacing: 4; &:hover{ border-radius: 20px; border: none; background-color: blueviolet; color: white; cursor: pointer; } `

#試したこと・考えたこと
・文字を入力する毎にbuttonタグにて設定しているonClickでのイベントが発火しているため、stateの更新によるレンダリングが起きていると考えた。
・上記理由から、親コンポーネントのonClickAddイベントに対してuseCallbaskを使用した。

以上、お忙しいところ大変恐縮ですが、
何卒、よろしくお願い申し上げます。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/06/15 08:23

> 再レンダリングでのループが起きてしまう。 その問題点は、どのように気づきましたか?
kimch

2021/06/15 08:28

maisumakun様 コメントありがとうございます。 エラー文からです。 エラー文を読み、推測して、親コンポーネントのonClickAddの中で`console.log("再レンダリング");`という記述をしたところ、inputタグに入力する度にconsole.logの内容が何度も表示されたことから判断しました。
guest

回答1

0

ベストアンサー

onClick={onClickAdd(todoTitle,todoText,todoLimit)}と書くと、「レンダリング時にonClickAddを実行して、その結果をonClickにセットする」という意味になってしまいます。

「クリック時にonClickAddを実行したい」のであれば、onClick={() => onClickAdd(todoTitle,todoText,todoLimit)}のように、「実行するとonClickAddを呼び出す関数」を渡す必要があります。

投稿2021/06/15 08:26

maisumakun

総合スコア146018

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kimch

2021/06/15 08:47

maisumakun様 ありがとうございます。 ご指摘いただきました点、全く認識ございませんでした。 勉強不足ですので、これからも勉強して参ります。 お忙しいところご回答いただきましたありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問