web-dev-qa-db-ja.com

reactjsのmap関数で状態を更新する方法

4つのボタンがあり、各ボタンには名前IDと選択されたブールフラグがあります。

私が達成しようとしているのは、ボタンをクリックすると、その特定のボタンのブールボタンフラグを変更することです。このため、その特定のボタンIDのマップ関数でsetStateを実行する必要があります。

私の問題は、特定のクリックされたボタンのマップ関数でsetStateを実行できないことです。そのbtnSelectedを変更する必要があります

私の目的は、複数選択の選択解除ボタンを作成することです。これは、ユーザーにとって興味のある選択であり、それに基づいて、UIと私の配列を反映しています。これが私のコードです。

期待してくれてありがとう。

import React, { Component } from "react";
import { Redirect } from "react-router-dom";

export default class Test extends Component {
  constructor(props, context) {
    super(props, context);

    this.handleChange = this.handleChange.bind(this);
    this.state = {
      value: "",
      numbers: [1, 2, 3, 4, 5],
      posts: [
        {
          id: 1,
          topic: "Animal",
          btnSelected: false
        },
        {
          id: 2,
          topic: "Food",
          btnSelected: false
        },
        {
          id: 3,
          topic: "Planet",
          btnSelected: false
        },
        { id: 4, topic: "Nature", btnSelected: false }
      ],
      allInterest: []
    };
  }

  handleChange(e) {
    //console.log(e.target.value);
    const name = e.target.name;
    const value = e.target.value;
    this.setState({ [name]: value });
  }

  getInterest(id) {
    this.state.posts.map(post => {
      if (id === post.id) {
        //How to setState of post only btnSelected should change
      }
    });
    console.log(this.state.allInterest);
    if (this.state.allInterest.length > 0) {
      console.log("Yes we exits");
    } else {
      console.log(id);
      this.setState(
        {
          allInterest: this.state.allInterest.concat(id)
        },
        function() {
          console.log(this.state);
        }
      );
    }
  }

  render() {
    return (
      <div>
        {this.state.posts.map((posts, index) => (
          <li
            key={"tab" + index}
            class="btn btn-default"
            onClick={() => this.getInterest(posts.id)}
          >
            {posts.topic}
            <Glyphicon
              glyph={posts.btnSelected === true ? "ok-sign" : "remove-circle"}
            />
          </li>
        ))}
      </div>
    );
  }
}
4
Mohammed Sabir

これは、次のようにする方法です。

class App extends Component {
  state = {
    posts: [{
      name: 'cat',
      selected: false,
    }, {
      name: 'dog',
      selected: false
    }]
  }

  handleClick = (e) => {
    const { posts } = this.state;
    const { id } = e.target;
    posts[id].selected = !this.state.posts[id].selected
    this.setState({ posts })
  }

  render() {
    return (
      <div>
        <form>
          {this.state.posts.map((p, i) => {
            return (
              <div>
                <label>{p.name}</label>
                <input type="radio" id={i} key={i} checked={p.selected} onClick={this.handleClick} />
              </div>
            )
          })}
        </form>
      </div>
    );
  }
}

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

動作例 ここ

3
Colin Ricardo

これを行うには、マップから各ボタンのhandleClick関数にインデックスを渡します。これにより、onClickイベントによってトリガーできる別の関数が返されます。

Colin Ricardoの回答とは対照的に、このアプローチでは、handleClickでインデックスを決定するためにのみ使用されるマップ関数の各子にidプロップを追加する必要がありません。比較を示すために、ここでColinの例を変更しました。イベントパラメータが不要になったことに注意してください。

class App extends Component {
  state = {
    posts: [{
      name: 'cat',
      selected: false,
    }, {
      name: 'dog',
      selected: false
    }]
  }

  handleClick = (index) => () => {
    const { posts } = this.state;
    posts[index].selected = !this.state.posts[index].selected
    this.setState({ posts })
  }

  render() {
    return (
      <div>
        <form>
          {this.state.posts.map((p, i) => {
            return (
              <div>
                <label>{p.name}</label>
                <input type="checkbox" key={i} checked={p.selected} onClick={this.handleClick(i)} />
              </div>
            )
          })}
        </form>
      </div>
    );
  }
}

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

動作例 ここ

0
Kevin Rickard