ReactのselectとonChange

https://qiita.com/y_ohr/items/4268d7287066d72cccbf の続き

# 概要

公式のフォーム項にあるselect タグを参考にselectを実装する
https://ja.reactjs.org/docs/forms.html#the-select-tag

# ３行まとめ

- ReactでselectとonChangeを実装した
- イベントハンドルに引数を渡した
- しかし、上記はパフォーマンス上の問題がある模様。https://ja.reactjs.org/docs/handling-events.html

# 実装

html再掲

```html:index.html
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />

    <title>Hello React!</title>

    <script src="https://unpkg.com/react@16/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
    <script src="https://unpkg.com/babel-standalone@6.26.0/babel.js"></script>
</head>

<body>
    <div id="root"></div>
</body>

</html>

<script type="text/babel" src="./app.js"></script>
```

jsxで`select`を追加し、`onChange`を実装

```react:app.js
class Square extends React.Component {
    constructor(props) {
        super(props);
        this.handleChange = this.handleChange.bind(this);
    }

    handleChange(e) {
        this.props.onNumberChange(e.target.value);
    }

    render() {
        return (
            <input
                type="text"
                value={this.props.number}
                className="square"
                onChange={this.handleChange}
            >
            </input>
        );
    }
}

const xyData = [
    { x: 0, o:'+', y: 1 },
    { x: 3, o:'-', y: 4 },
    { x: 6, o:'*', y: 7 },
];

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            xyData
        };
    }

    renderSquare(i, m) {
        return <Square number={i} onNumberChange={m} />;
    }

    toNumber(n) {
        return n * 1;
    }

    calcXY(x, o, y) {
        const numx = this.toNumber(x);
        const numy = this.toNumber(y);
        switch (o) {
            case '+': return numx + numy;
            case '-': return numx - numy;
            case '*': return numx * numy;
            case '/': return numx / numy;
            default: return 0;
        }
    }

    updateOperator(index, event) {
        const xyData = this.state.xyData.slice();
        xyData[index].o = event.target.value;
        this.setState({ xyData });
    }

    render() {
        const title = 'XY演算機';
        const xyData = this.state.xyData.slice();
        return (
            <div>
                <div className="title">{title}</div>
                {xyData.map((value, i) => (
                    <div className="board-row">
                        {this.renderSquare(value.x,
                            (e) => {
                                xyData[i].x = e;
                                this.setState({ xyData });
                            })
                        }
                        <select value={value.o} onChange={(e) => { this.updateOperator(i, e) }}>
                            <option value="+">＋</option>
                            <option value="-">－</option>
                            <option value="*">×</option>
                            <option value="/">÷</option>
                        </select>
                        {this.renderSquare(value.y,
                            (e) => {
                                xyData[i].y = e;
                                this.setState({ xyData });
                            })
                        }
                        =
                        <input value={this.calcXY(value.x, value.o, value.y)} />
                    </div>
                ))}
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'))
```

# 実行結果

算術演算子を変更すると、合計が再レンダリングされます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/215001/fe08e79b-1d29-e3b0-0c8b-a386432949d7.png)


# 感想

- keyの警告が出続けているので除去したい
- イベントハンドラに引数を渡す方法で躓いたけど、公式にあった。https://ja.reactjs.org/docs/handling-events.html#passing-arguments-to-event-handlers
- そろそろtypescriptも使ってみたい
- 式の追加や削除、挿入を実装してみたい
- keypressを実装してみたい

以上