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

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

新規登録して質問してみよう
ただいま回答率
85.48%
React.js

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

Q&A

解決済

1回答

785閲覧

setStateで関数を引数にした書き方

moriman

総合スコア615

React.js

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

0グッド

0クリップ

投稿2019/07/26 00:23

React

1<html> 2<head> 3<meta http-equiv="content-type" charset="utf-8"> 4<style> 5h1{ 6 display: inline; 7} 8h2{ 9 display: inline; 10} 11.button_inc{ 12 width: 250px; 13 border-radius: 0; 14 font-size : 30pt; 15 padding: 10px 10px; 16 background-color: red; 17 display: inline-block; 18} 19.button_dec{ 20 width: 250px; 21 border-radius: 0; 22 font-size : 30pt; 23 padding: 10px 10px; 24 background-color: blue; 25 display: inline-block; 26} 27.submit_inc{ 28 29 -webkit-appearance: none; 30 border-radius: 0; 31 font-size : 30pt; 32 padding: 10px 10px; 33 background-color: pink; 34 display: inline-block; 35} 36.submit_dec{ 37 -webkit-appearance: none; 38 border-radius: 0; 39 font-size : 30pt; 40 padding: 10px 10px; 41 background-color: blue; 42 display: inline-block; 43} 44.nor_css{ 45 width:400px; 46 background-color: yellow; 47 font-size : 30px; 48 padding: 10px 10px; 49 display: inline-block; 50 text-align: center; 51} 52.wm_css{ 53 background-color: green; 54 font-size: 30px; 55 padding: 10px 10px; 56} 57.cs_css{ 58 background-color: red; 59 font-size: 30px; 60 padding: 10px 10px; 61} 62.cw_css{ 63 background-color: pink; 64 font-size: 30px; 65 padding: 10px 10px; 66} 67.ver{ 68 font-size : 50px; 69 background-color: pink; 70} 71.mess_box{ 72 73 width: 400px; 74 border: solid blue; 75} 76div#root2{ 77 background-color: pink; 78 font-size: 30px; 79 width: 400px; 80 border: solid blue; 81} 82</style> 83 84 <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> 85 <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> 86 <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script> 87 88</head> 89<body> 90 91 <div id="root">root</div> 92 93 94 95 <script type="text/babel"> 96 class App extends React.Component{ 97 98 constructor(props){ 99 super(props); 100 this.state={ 101 aaa : 0, 102 bbb : 0, 103 mess : "" 104 } 105 } 106 107 handleClickInc(e){ 108 alert(e.timeStamp+"に"+e.target.name+"を増やしました。"); 109 this.setState({[e.target.name]:this.state[e.target.name]+1,mess:"aaaを1増やしました。"}); 110 } 111 112 handleClickDec(e){ 113 alert(e.timeStamp+"に"+e.target.name+"減らしました。"); 114 this.setState({[e.target.name]:this.state[e.target.name]-1,mess:"aaaを1減らしました。"}); 115 } 116 117 118 119 render(){ 120 return( 121 <div> 122 <p>{this.state.aaa}</p> 123 <p>{this.state.bbb}</p> 124 <MessBox mess={this.state.mess}/> 125 <h1>aaa</h1> 126 <MyState nor={this.state.aaa} name="aaa" inc_mess="+1" dec_mess="-1" onClickInc={(e)=>this.handleClickInc(e)} onClickDec={(e)=>this.handleClickDec(e)}/> 127 <h1>bbb</h1> 128 <MyState nor={this.state.bbb} name="bbb" inc_mess="+1" dec_mess="-1" onClickInc={(e)=>this.handleClickInc(e)} onClickDec={(e)=>this.handleClickDec(e)}/> 129 </div> 130 ) 131 } 132 } 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 class MessBox extends React.Component{ 148 render(){ 149 return( 150 <div id="mess_box" class="mess_box"> 151 {this.props.mess} 152 </div> 153 ) 154 } 155 } 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 class MyState extends React.Component { 171 constructor(props) { 172 super(props); 173 this.state = { 174 current : new Date(), 175 nor : 0, 176 mess : "" 177 }; 178 179 this.onSubmitInc=this.onSubmitInc.bind(this); 180 this.onSubmitDec=this.onSubmitDec.bind(this); 181 } 182 183 onSubmitInc(e){ 184 console.log(e.type); 185 console.log(e.target.name); 186 console.log(e.currentTarget); 187 this.props.onClickInc(e); 188 this.setState({nor:this.state.nor+1}); 189 document.cookie = 'nor='+this.state.nor; 190 //alert(document.cookie); 191 } 192 193 onSubmitDec(e){ 194 console.log(e.type); 195 console.log(e.target.name); 196 console.log(e.currentTarget); 197 this.props.onClickDec(e); 198 this.setState({nor:this.state.nor-1}); 199 } 200 201 render() { 202 //document.cookie = 'nor='+this.state.nor; 203 console.log(document.cookie); 204 return ( 205 <div> 206 <h1>{this.props.rolltype}</h1> 207 <form action="" method="POST"> 208 <table> 209 <tr> 210 <td> 211 <input className ="button_inc" type="button" name={this.props.name} value={this.props.inc_mess} onClick={this.onSubmitInc}/> 212 {/*<input className ="button_inc" type="button" name={this.props.name} value={this.props.inc_mess} onClick={this.props.onClickInc}/>*/} 213 </td> 214 <td> 215 <div className ="nor_css"><h1>{this.state.nor}</h1> 回<h2>{this.props.nor}</h2>回</div> 216 </td> 217 <td> 218 <input className ="button_dec" type="button" name={this.props.name} value={this.props.dec_mess} onClick={this.onSubmitDec}/> 219 {/*<input className ="button_dec" type="button" name={this.props.name} value={this.props.dec_mess} onClick={this.props.onClickDec}/>*/} 220 </td> 221 </tr> 222 </table> 223 </form> 224 <hr/> 225 </div> 226 ) 227 } 228} 229 230 ReactDOM.render(<App />, document.getElementById('root')); 231 </script> 232 233 234</body> 235</html> 236

Reactの練習でクリックカウンタを作っています。とりあえず上記コードで期待通りに動いているんですが、AppコンポーネントのhandleClickInc内の

this.setState({[e.target.name]:this.state[e.target.name]+1,mess:"aaaを1増やしました。"});

の書き方は良くないというのをドキュメントで見たので、setStateの引数を関数にして書き直したいのですが、書き直してみるとエラーが出ます。
以下、書き直したコード↓↓

handleClickInc(e){ alert(e.timeStamp+"に"+e.target.name+"を増やしました。"); this.setState((prevState, props) =>({[e.target.name]:prevState[e.target.name]+1,mess:"aaaを1増やしました。"})); } handleClickDec(e){ alert(e.timeStamp+"に"+e.target.name+"減らしました。"); this.setState((prevState, props) =>({[e.target.name]:prevState[e.target.name]-1,mess:"aaaを1減らしました。"})); }

以下、出力されたエラー↓↓

TypeError: Cannot read property 'name' of null at App.<anonymous> (<anonymous>:36:54) at xg (react-dom.production.min.js:114) at Cb (react-dom.production.min.js:114) at qg (react-dom.production.min.js:95) at hi (react-dom.production.min.js:104) at Qg (react-dom.production.min.js:144) at Rg (react-dom.production.min.js:145) at Sc (react-dom.production.min.js:158) at Z (react-dom.production.min.js:156) at ah (react-dom.production.min.js:159)

関数を引数にしたsetStateの書き方が間違っているとしか思えないのですが、どこを見ればわかるでしょうか?できれば正しい書き方を教えて頂けるとありがたいです。

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

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

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

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

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

guest

回答1

0

ベストアンサー

できれば正しい書き方を教えて頂けるとありがたいです。

this.setStateに関数を渡した場合、それは非同期実行されます。さらに、Reactのイベントオブジェクトは効率化のために使い回されますので、非同期実行のときには値が取れなくなっています(公式)。

e.targetから取得すべき値を、setStateを呼ぶ前に取得しておきましょう。

javascript

1 handleClickInc(e){ 2 alert(e.timeStamp+"に"+e.target.name+"を増やしました。"); 3 const {name} = e.target; 4 this.setState((prevState, props) =>({[name]:prevState[name]+1,mess:"aaaを1増やしました。"})); 5 } 6 7 handleClickDec(e){ 8 alert(e.timeStamp+"に"+e.target.name+"減らしました。"); 9 const {name} = e.target; 10 this.setState((prevState, props) =>({[name]:prevState[name]-1,mess:"aaaを1減らしました。"})); 11 }

投稿2019/07/26 00:44

maisumakun

総合スコア145183

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

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

moriman

2019/07/26 00:53

早速回答を頂きましてありがとうございます。無知で申し訳ないのですが、 const {name} = e.target; この文法を知らないのですが、これは何をしているんでしょうか?(苦笑) 検索するためのキーワードとか構文名みたいなのはありますでしょうか?
maisumakun

2019/07/26 00:55

分割代入、といいます。やっていることは「const name = e.target.name;」と同じです。
moriman

2019/07/26 01:07

ヒントを頂きましてありがとうございます。すみません、最後に、 私が最初に挙げてエラーが出たコードなんですが、なぜエラーが出る んでしょうか? nullとエラーで出てるんですが、どうも最初の書き方でも行けそうな気が してしまうのですが、どこが悪いんでしょうか?
maisumakun

2019/07/26 01:10 編集

質問に回答したように、setStateに渡した関数が実行される前にeの中身が書き換わってしまうからです。
moriman

2019/07/26 01:10

というかその「なぜ悪いか」を一番最初に説明して頂いてるんですね(笑) setIntervalの例で速習Reactに説明があったと思うんですが、多分その部分ですね。 もう一度見直してみます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問