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

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

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

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

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

Q&A

解決済

1回答

2950閲覧

Reactで以前のstateの値を取得するには

Udomomo

総合スコア1524

TypeScript

TypeScriptは、マイクロソフトによって開発された フリーでオープンソースのプログラミング言語です。 TypeScriptは、JavaScriptの構文の拡張であるので、既存の JavaScriptのコードにわずかな修正を加えれば動作します。

React.js

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

0グッド

0クリップ

投稿2017/10/04 01:32

ReactとTypeScriptでスロットゲームを作っています。ボタンを押すと複数のサイコロを押すというものです。
このスロットの追加機能として、サイコロごとにチェックボックスをつけ、チェックがついたサイコロはボタンを押しても回転しないようにしたいと思っています。

このとき、チェックがついたサイコロだけ再レンダリングさせないためにはどうすればいいかで悩んでいます。

今のコードは以下です。

TypeScript

1import * as React from 'react'; 2import * as ReactDOM from 'react-dom'; 3 4interface IndexProps { 5} 6 7interface IndexState { 8 rolling: boolean; 9 dicePip: Array<string>; 10} 11 12class Index extends React.Component<IndexProps, IndexState> { 13 timerId: number; 14 constructor(props: IndexProps) { 15 super(props); 16 this.state = { 17 rolling: false, 18 dicePip: ['\u2680', '\u2680', '\u2680', '\u2680', '\u2680', '\u2680', '\u2680', '\u2680', 19 '\u2680', '\u2680', '\u2680', '\u2680', '\u2680', '\u2680', '\u2680', '\u2680'] 20 } 21 this.buttonClick = this.buttonClick.bind(this); 22 } 23 static pipsList = ['\u2680', '\u2681', '\u2682', '\u2683', '\u2684', '\u2685']; 24 buttonClick(): void { 25 this.setState({ 26 rolling: true 27 }); 28 this.runSlot(); 29 } 30 runSlot(): void { 31 let counter: number = 0; 32 this.timerId = setInterval( 33 () => { 34 this.randomDicePips(); 35 counter++; 36 if (counter >= 20) { 37 clearInterval(this.timerId); 38 this.stopSlot(); 39 } 40 }, 50 41 ); 42 } 43 randomDicePips(): void { 44 let nextPips: Array<string> = new Array; 45 for (let i=0; i<16; i++) { 46 nextPips.push(Index.pipsList[Math.floor(Math.random() * Index.pipsList.length)]); 47 } 48 this.setState({ 49 dicePip: nextPips 50 }) 51 } 52 stopSlot(): void { 53 this.setState({ 54 rolling: false 55 }); 56 } 57 render() { 58 let diceElements: Array<JSX.Element> = new Array; 59 for (let i=0; i<16; i++) { 60 diceElements.push( 61 <Dice className="dice" dicePips={this.state.dicePip[i]} id={'cb' + String(i)} rolling = {this.state.rolling}/> 62 ); 63 } 64 return ( 65 <div> 66 <div id="container"> 67 {diceElements} 68 </div> 69 <div id = "menu"> 70 <Button buttonClick = {this.buttonClick} rolling = {this.state.rolling}/> 71 </div> 72 </div> 73 ); 74 } 75} 76 77interface DiceProps { 78 className: string; 79 dicePips: string; 80 id: string; 81 rolling: boolean; 82} 83 84class Dice extends React.Component<DiceProps> { 85 constructor (props: DiceProps) { 86 super(props); 87 } 88 89 render() { 90 return ( 91 <div className='panel'> 92 <div className={this.props.className}>{this.props.dicePips}</div> 93 <div className="hold"><input type="checkbox" id={this.props.id} disabled /><label htmlFor={this.props.id}>Hold</label></div> 94 </div> 95 ); 96 } 97} 98 99interface ButtonProps { 100 buttonClick(): void; 101 rolling: boolean; 102} 103 104const Button: React.StatelessComponent<ButtonProps> = (props) => { 105 return ( 106 <div id="button" className={props.rolling ? "inactive" : ""} onClick={props.buttonClick}> 107 <span id="label">Roll</span> 108 </div> 109 ); 110}

現状では、ボタンを押すとrunslotメソッドが呼び出され、その内部ではrandomDicePipsメソッドをsetIntervalで繰り返し呼んでいます。
randomDicePipsメソッドの中では、出された値をnextPipsというArrayの中に入れ、そのArrayを新しいdicePipStateとし、各サイコロの目としてレンダリングしています。

nextPipsArrayを作る際に、チェックされたサイコロのみ以前のStateの値を入れるようにすればよいと思っているのですが、どのようにその値を取得すればよいのか、うまい方法が思いついていません。
何か良い手はあるでしょうか?

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

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

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

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

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

guest

回答1

0

ベストアンサー

こんなかんじでいいんですかね。あまりReactにdocument.getElement~を持ち込みたくないですが、せっかくidをチェックボックスに付与しているのでこれを利用して取得してみました。
多分これが一番早いと思います。

javascript

1 2 randomDicePips(): void { 3 let nextPips: Array<string> = new Array; 4 for (let i=0; i<16; i++) { 5 // idから該当のチェックボックスのelementを取得 6 let checkbox = document.getElementById('cb' + i); 7 let pip = null; 8 // チェック状態の確認 9 if(checkbox.checked) { 10 // this.state.dicePipから前回の値を引き継ぐ 11 pip = this.state.dicePip[i]; 12 } 13 else { 14 // 従来通りランダムに取る 15 pip = Index.pipsList[Math.floor(Math.random() * Index.pipsList.length)]; 16 } 17 nextPips.push(pip); 18 } 19 this.setState({ 20 dicePip: nextPips 21 }) 22 }

あれ?でもこれDiceが再レンダリングされたらチェックボックスの状態が元に戻ってしまうのでは…?

投稿2017/10/04 02:10

masaya_ohashi

総合スコア9206

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

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

Udomomo

2017/10/05 03:49

`document.getElement`を使う手がありましたね。ありがとうございます。 チェックボックスの状態が元に戻るのは確かにその通りです...気づきませんでした。どう対応するかは改めて考えてみます。
masaya_ohashi

2017/10/05 04:04

本当はチェックボックスの対応も方法はわかっているのですが書いたらかなり既存コードを書き換えてしまうので、自分でまずは試してみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問