JSのスプレッド演算子でハマったこと

###はじめに

React, Reduxを学び始めて `Spread演算子` を触る機会が増えてきた。自分がはまった点を他の初学者の方のために共有しようと思います。

###1. ReactのオブジェクトSpread演算子ではまった
---
オブジェクトに対してSpread演算子を使用すると
`Module build failed: SyntaxError: Unexpected token`
とerrorが出て `Spread演算子` が`Object`に対してデフォルトで使用出来なかった。

![](https://i.gyazo.com/551351c8fdd5ea511f1560afaa199aa1.png)

**解決方法**
標準では`Object`のSpread演算子はサポートしていないので、Babelに追加のpluginを導入することで解決。

https://babeljs.io/docs/en/babel-plugin-transform-object-rest-spread

###2. データの渡し方ではまった
---

以下の画像のように、テキストを打ち込むと配列に新しいデータが追加できるようなコードを作成する

![](https://gyazo.com/7ceb4b2b614ea8d1f03834ee4cf94b21.gif)

最初に記述していたコード 

```sample.js
import React from 'react';
import ReactDOM from 'react-dom';

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fruits: ['Apple', 'Banana', 'Orange', 'Cherry', 'Pineapple']
    };
  }
  handleClick = (text) => {
    this.setState({
      ...this.state,
      fruits: [text]
    });
  }
  handleAddText = (e) => {
    e.preventDefault();
    const option = e.target.elements.option.value.trim();
    this.handleClick(option)
    e.target.elements.option.value = '';
  }
  render() {
    console.log(this.state)
    return (
      <div>
        {this.state.fruits.map((fruit, index) => (
        <Child 
          key={index}
          data={fruit} 
        />
        )
        )}
      <form onSubmit={this.handleAddText}>
        <input type="text" name="option" />
        <button>Add Option</button>
      </form>
      </div>
    );
  }
}

const Child = (props) => (
  <div onClick={props.handleClick}>
    {props.data}
  </div>
);

ReactDOM.render(<Parent />, document.getElementById('app'))
```

![](https://gyazo.com/0ff828cb46b5be87520ac9a4637e70ce.gif)

上記の記述だと、毎回 valueの配列そのものが更新されてしまい、Objectのvalueである**Array**に要素の追加が出来なかった。

Objectのvalueである**Array**に要素の追加のみを記述するには、指定したキー(fruits)の中で更に `spread演算子` で **Array**のみを取り出し、要素をそれから記述する必要があった。

```sample.js
import React from 'react';
import ReactDOM from 'react-dom';

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fruits: ['Apple', 'Banana', 'Orange', 'Cherry', 'Pineapple']
    };
  }
  handleClick = (text) => {
    this.setState({
      ...this.state,
      fruits: [
        ...this.state.fruits,
        text
      ]
    });
  }
  handleAddText = (e) => {
    e.preventDefault();
    const option = e.target.elements.option.value.trim();
    this.handleClick(option)
    e.target.elements.option.value = '';
  }
  render() {
    console.log(this.state)
    return (
      <div>
        {this.state.fruits.map((fruit, index) => (
        <Child 
          key={index}
          data={fruit} 
        />
        )
        )}
      <form onSubmit={this.handleAddText}>
        <input type="text" name="option" />
        <button>Add Option</button>
      </form>
      </div>
    );
  }
}

const Child = (props) => (
  <div onClick={props.handleClick}>
    {props.data}
  </div>
);

ReactDOM.render(<Parent />, document.getElementById('app'))
```

###3. 付録 (concatの記述と比較)
---

上記のコードはconcatを使用して下記のようにも記述出来る。

```sample.js
import React from 'react';
import ReactDOM from 'react-dom';

class Parent extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      fruits: ['Apple', 'Banana', 'Orange', 'Cherry', 'Pineapple']
    };
  }
  handleClick = (text) => {
    this.setState((prevState) => ({
      fruits: prevState.fruits.concat(text)
    }));
  }
  handleAddText = (e) => {
    e.preventDefault();
    const option = e.target.elements.option.value.trim();
    this.handleClick(option)
    e.target.elements.option.value = '';
  }
  render() {
    console.log(this.state)
    return (
      <div>
        {this.state.fruits.map((fruit, index) => (
        <Child 
          key={index}
          data={fruit} 
        />
        )
        )}
      <form onSubmit={this.handleAddText}>
        <input type="text" name="option" />
        <button>Add Option</button>
      </form>
      </div>
    );
  }
}

const Child = (props) => (
  <div onClick={props.handleClick}>
    {props.data}
  </div>
);

ReactDOM.render(<Parent />, document.getElementById('app'))
```