Posted at

Reactのinput(複数inputで成功)

https://qiita.com/y_ohr/items/ecfaf31176c3ad554bf2 の続きです。


環境

Ubuntu 18.04.2 LTS

node v8.10.0
npm 3.5.2
create-react-app v2.1.5


3行まとめ


  • 複数のinputを連動させるためstateを、親コンポーネントへリフトアップした

  • 合わせてsetState()も、親コンポーネントへリフトアップし、子のhandleChangeで発火するようにした

  • 複数のinputが連動できた


複数inputが連動するように修正


src/index.js

--- a/src/index.js

+++ b/src/index.js
@@ -4,18 +4,20 @@ import ReactDOM from 'react-dom';
class Square extends React.Component {
constructor(props) {
super(props);
- this.state = {
- value: props.value
- }
+ this.handleChange = this.handleChange.bind(this);
+ }
+
+ handleChange(e){
+ this.props.onNumberChange(e.target.value);
}

render() {
return (
<input
type="text"
- value={this.state.value}
+ value={this.props.number}
className="square"
- onChange={e => this.setState({ value: e.target.value })}
+ onChange={this.handleChange}
>
</input>
);
@@ -23,36 +25,83 @@ class Square extends React.Component {
}

class Board extends React.Component {
- renderSquare(i) {
- return <Square value={i} />;
+ constructor(props) {
+ super(props);
+
+ this.handleX1Change = this.handleX1Change.bind(this);
+ this.handleY1Change = this.handleY1Change.bind(this);
+ this.handleX2Change = this.handleX2Change.bind(this);
+ this.handleY2Change = this.handleY2Change.bind(this);
+ this.handleX3Change = this.handleX3Change.bind(this);
+ this.handleY3Change = this.handleY3Change.bind(this);
+
+ this.state = {
+ x1: 0, y1: 1,
+ x2: 3, y2: 4,
+ x3: 6, y3: 7,
+ };
+ }
+
+ handleX1Change(x1) {
+ this.setState({ x1 });
+ }
+
+ handleY1Change(y1) {
+ this.setState({ y1 });
+ }
+
+ handleX2Change(x2) {
+ this.setState({ x2 });
+ }
+
+ handleY2Change(y2) {
+ this.setState({ y2 });
+ }
+
+ handleX3Change(x3) {
+ this.setState({ x3 });
+ }
+
+ handleY3Change(y3) {
+ this.setState({ y3 });
+ }
+
+ renderSquare(i, m) {
+ return <Square number={i} onNumberChange={m} />;
}

render() {
- const status = 'Next player: X';
+ const title = 'XY<E5><8A><A0><E7><AE><97><E6><A9><9F>';
+ const sum1 = parseInt(this.state.x1, 10) + parseInt(this.state.y1, 10);
+ const sum2 = parseInt(this.state.x2, 10) + parseInt(this.state.y2, 10);
+ const sum3 = parseInt(this.state.x3, 10) + parseInt(this.state.y3, 10);

return (
<div>
- <div className="status">{status}</div>
+ <div className="title">{title}</div>
<div className="board-row">
- {this.renderSquare(0)}
+ 1
+ {this.renderSquare(this.state.x1, this.handleX1Change)}
+
- {this.renderSquare(1)}
+ {this.renderSquare(this.state.y1, this.handleY1Change)}
=
- {this.renderSquare(1)}
+ {this.renderSquare(sum1)}
</div>
<div className="board-row">
- {this.renderSquare(3)}
+ 2
+ {this.renderSquare(this.state.x2, this.handleX2Change)}
+
- {this.renderSquare(4)}
+ {this.renderSquare(this.state.y2, this.handleY2Change)}
=
- {this.renderSquare(7)}
+ {this.renderSquare(sum2)}
</div>
<div className="board-row">
- {this.renderSquare(6)}
+ 3
+ {this.renderSquare(this.state.x3, this.handleX3Change)}
+
- {this.renderSquare(7)}
+ {this.renderSquare(this.state.y3, this.handleY3Change)}
=
- {this.renderSquare(13)}
+ {this.renderSquare(sum3)}
</div>
</div>
);


複数コンポーネントが連動した!

image.png


感想


  • どう見ても冗長なので何とかしたい

  • 子から親へのonChangeのイメージが乏しい

  • 当初、sumはstateにしていたが、stateのxとyから算出できるので、stateはやめた


  • sumの計算は静的に見えるが、state更新時に動的に計算される

  • stateが更新されるとrender()が実行され、結果の差分のみレンダリングされる?

  • 縦合計も出したい

  • 四則演算に対応したい

以上