LoginSignup
3
4

More than 5 years have passed since last update.

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

Posted at

はじめに

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

1. ReactのオブジェクトSpread演算子ではまった


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

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

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


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

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

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'))

上記の記述だと、毎回 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'))
3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4