<html> <head> <meta http-equiv="content-type" charset="utf-8"> <style> h1{ display: inline; } h2{ display: inline; } .button_inc{ width: 250px; border-radius: 0; font-size : 30pt; padding: 10px 10px; background-color: red; display: inline-block; } .button_dec{ width: 250px; border-radius: 0; font-size : 30pt; padding: 10px 10px; background-color: blue; display: inline-block; } .submit_inc{ -webkit-appearance: none; border-radius: 0; font-size : 30pt; padding: 10px 10px; background-color: pink; display: inline-block; } .submit_dec{ -webkit-appearance: none; border-radius: 0; font-size : 30pt; padding: 10px 10px; background-color: blue; display: inline-block; } .nor_css{ width:400px; background-color: yellow; font-size : 30px; padding: 10px 10px; display: inline-block; text-align: center; } .wm_css{ background-color: green; font-size: 30px; padding: 10px 10px; } .cs_css{ background-color: red; font-size: 30px; padding: 10px 10px; } .cw_css{ background-color: pink; font-size: 30px; padding: 10px 10px; } .ver{ font-size : 50px; background-color: pink; } .mess_box{ width: 400px; border: solid blue; } div#root2{ background-color: pink; font-size: 30px; width: 400px; border: solid blue; } </style> <script src="https://unpkg.com/react@16/umd/react.production.min.js"></script> <script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script> <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script> </head> <body> <div id="root">root</div> <script type="text/babel"> class App extends React.Component{ constructor(props){ super(props); this.state={ aaa : 0, bbb : 0, mess : "" } } handleClickInc(e){ {/*alert(e.timeStamp+"に"+e.target.name+"を増やしました。");*/} {/*this.setState({[e.target.name]:this.state[e.target.name]+1,mess:"aaaを1増やしました。"});*/} const {name} = e.target; this.setState((prevState, props) =>({[name]:prevState[name]+1,mess:"aaaを1増やしました。"})); } handleClickDec(e){ {/*alert(e.timeStamp+"に"+e.target.name+"減らしました。");*/} {/*this.setState({[e.target.name]:prevState[e.target.name]-1,mess:"aaaを1減らしました。"});*/} const {name} = e.target; this.setState((prevState, props) =>({[name]:prevState[name]-1,mess:"aaaを1減らしました。"})); } componentDidUpdate(prevProps,prevState){ {/*document.cookie = 'aaa='+this.state.aaa;*/} {/*document.cookie = 'bbb='+this.state.bbb;*/} {/* localStorage.setItem('aaa',this.state.aaa); localStorage.setItem('bbb',this.state.bbb); */} localStorage.setItem('aaa',this.state.aaa); localStorage.setItem('bbb',this.state.bbb); } render(){ return( <div> <p>{localStorage.getItem('aaa')}</p> <p>{localStorage.getItem('bbb')}</p> <MessBox mess={this.state.mess}/> <h1>aaa</h1> <MyState nor={this.state.aaa} name="aaa" inc_mess="+1" dec_mess="-1" onClickInc={(e)=>this.handleClickInc(e)} onClickDec={(e)=>this.handleClickDec(e)}/> <h1>bbb</h1> <MyState nor={this.state.bbb} name="bbb" inc_mess="+1" dec_mess="-1" onClickInc={(e)=>this.handleClickInc(e)} onClickDec={(e)=>this.handleClickDec(e)}/> </div> ) } } class MessBox extends React.Component{ render(){ return( <div id="mess_box" class="mess_box"> {this.props.mess} </div> ) } } class MyState extends React.Component { constructor(props) { super(props); this.state = { current : new Date(), nor : 0, mess : "" }; this.onSubmitInc=this.onSubmitInc.bind(this); this.onSubmitDec=this.onSubmitDec.bind(this); } onSubmitInc(e){ console.log(e.type); console.log(e.target.name); console.log(e.currentTarget); this.props.onClickInc(e); this.setState({nor:this.state.nor+1}); document.cookie = 'nor='+this.state.nor; //alert(document.cookie); } onSubmitDec(e){ console.log(e.type); console.log(e.target.name); console.log(e.currentTarget); this.props.onClickDec(e); this.setState({nor:this.state.nor-1}); } resetLs(){ localStorage.setItem('aaa',0); localStorage.setItem('bbb',0); } render() { //document.cookie = 'nor='+this.state.nor; console.log(document.cookie); return ( <div> <h1>{this.props.rolltype}</h1> <form action="" method="POST"> <table> <tr> <td> <input className ="button_inc" type="button" name={this.props.name} value={this.props.inc_mess} onClick={this.onSubmitInc}/> {/*<input className ="button_inc" type="button" name={this.props.name} value={this.props.inc_mess} onClick={this.props.onClickInc}/>*/} </td> <td> <div className ="nor_css"><h1>{this.state.nor}</h1> 回<h2>{this.props.nor}</h2>回</div> </td> <td> <input className ="button_dec" type="button" name={this.props.name} value={this.props.dec_mess} onClick={this.onSubmitDec}/> {/*<input className ="button_dec" type="button" name={this.props.name} value={this.props.dec_mess} onClick={this.props.onClickDec}/>*/} </td> </tr> </table> </form> <hr/> <button id="reset" onClick={this.resetLs}>ローカルストレージリセット</button> </div> ) } } ReactDOM.render(<App />, document.getElementById('root')); </script> </body> </html>
reactの練習でクリックカウンタを作っています。上記コードで一応動くのですが、MyStateコンポーネントを配置する時に繰り返しを使ってやれないかと考えています。
現時点でのざっくりした流れとして
(1)Appコンポーネントのrenderメソッド内で
<MyState nor={this.state.aaa} name="aaa" inc_mess="+1" dec_mess="-1" onClickInc={(e)=>this.handleClickInc(e)} onClickDec={(e)=>this.handleClickDec(e)}/>
としてnameプロパティの"aaa"をMyStateコンポーネントに渡す。
(2)MyStateコンポーネント内で
<input className ="button_inc" type="button" name={this.props.name} value={this.props.inc_mess} onClick={this.onSubmitInc}/>
とすることで、MyStateコンポーネントのボタンが押された時にAppコンポーネントに用意したイベントハンドラhandleClickInc(e)が呼び出される。その時e.target.nameにより"aaa"が渡される。
(3)Appのstate.aaaにカウント数が1加算されてセットされる。
という流れで、一応動きます。しかしこれだとMyStateを多数配置したい時、配置したい数の分コピペすることになるので、できれば以下のようにやりたいと考えています。
(1)Appクラスのstateを例えば、
class App extends React.Component{ constructor(props){ super(props); this.state={ types : [{name:'aaa',count:0,roletype:'りんご'}, {name:'bbb',count:0,roletype:'みかん'}], mess : "" } }
のようにして、
(2)Appコンポーネントのrenderメソッド内で、
render() return( {this.state.types.map((type)=> <MyState roletype={type.roletype} nor={type.count} name={type.name} inc_mess="+1" dec_mess="-1" onClickInc={(e)=>this.handleClickInc(e)} onClickDec={(e)=>this.handleClickDec(e)}/> } )
↑のようにして繰り返しでMyStateコンポーネントをレンダーする。
これができないか考えています。
この時Appコンポーネントのイベントハンドラ(handleClickInc,handleClickDec)のsetStateの部分も書き直す必要があるのですが、ここの書き方がわかりません。computed property namesを使って動的にセットするstateを指定したいです。
handleClickIncを、
handleClickInc(e){ const {name} = e.target; this.setState((prevState, props) =>({types.[name]:prevState.types.[name]+1,mess:"aaaを1増やしました。"})); }
↑のように書くと、
Uncaught SyntaxError: Inline Babel script: Unexpected token, expected , (17:56) 15 | {/*this.setState({[e.target.name]:this.state[e.target.name]+1,mess:"aaaを1増やしました。"});*/} 16 | const {name} = e.target; > 17 | this.setState((prevState, props) =>({types.[name]:prevState.types.[name]+1,mess:"aaaを1増やしました。"})); | ^ 18 | }
↑のようなエラーが出ます。
setStateの引数でComputed property namesを使って、上記のようなstateを指定することはできるのでしょうか?
(具体的に言うと、"aaa"のボタンを押したときに、Appのstateの対応する部分(stateのプロパティ)を取得してセットしたい、ということですが、整理できてなくてすみません。整理できないのは最初のstateの設定の仕方がまずいからかとも思っています。)
回答1件
あなたの回答
tips
プレビュー