简体   繁体   English

在React中映射数组

[英]Mapping over arrays in React

I'm mapping over each object inside the array of objects inside my state's item property. 我正在状态状态的item属性内的对象数组内映射每个对象。 The issue is, I want to be able to attach a button to each returned item that only works with that item, and not the other items too. 问题是,我希望能够将按钮附加到仅适用于该项目的每个返回项目,而不适用于其他项目。 Here's what I have so far: 这是我到目前为止的内容:

class App extends React.Component {
    state = {
        item: [],
    }
    componentDidMount() {
        this.setState({
            item: [
                {
                    name: 'jacob',
                    hair: 'brown',
                    sex: 'male',
                }, {
                    name: 'hannah',
                    hair: 'brown',
                    sex: 'female',
                }
            ]
        })
    }
    handleChange = (e) => {
        console.log(e.target.value)
        var x = Object.assign({}, this.state)
    }
    render() {
        return(
            <div>
                { this.state.item.length > 0 ? 
                    (
                        <div className="row mt-5">
                            <Item item={ this.state.item } handleChange={ this.handleChange } />
                        </div>
                    ) : null
                }
            </div>
        )
    }
}

class Item extends React.Component {
    render() {
        return(
            <div className="col">
                { this.props.item.map(s => (
                    <div>
                        <div className="mt-5">{ s.name }</div>
                        <button onClick={ this.props.handleChange } value={ s.name }>Click</button>
                    </div>
                 ))}
            </div>
        )
    }
}

So for instance, if the button's fx was to change the name property of the item it was rendered with, I want it to only change that item and no other items should be affected. 因此,例如,如果按钮的fx更改了与之一起渲染的项目的name属性,我希望它更改该项目,而不会影响其他项目。 Whenever I iterate through it attaches the button's fx to every item, so if I click it for one, I'm really clicking it for all of them, and that's exactly what I don't want. 每当我遍历它时,都会将按钮的fx附加到每个项目上,因此,如果我单击它的一个项目,则实际上是对所有项目都单击它,而这正是我所不想要的。

For those curious, I'm setting the state in componentDidMount to simulate calling an API. 对于那些好奇的人,我在componentDidMount中设置状态以模拟调用API。

Also, the fx that's currently running in the handleChange is just some messing around I was doing trying to figure out values and a solution to manipulating a nested object inside an array. 另外,handleChange中当前正在运行的fx只是在弄乱我正在尝试找出值以及操纵数组内嵌套对象的解决方案而已。

I think you want to pass the individual element in to your handleChange : 我认为您想将单个元素传递到您的handleChange

  { this.props.item.map((s, i) => {
      <div>
        <div className="mt-5">{ s.name }</div>
        <button key={i} onClick={ (s) => this.props.handleChange(s) } value={ s.name }>Click</button>
      </div>
   })}

This way, you will have the individual item passed in as an argument, so when you are writing your handleChange , you can do whatever you want with just that item and not the whole array. 这样,您将把单个item作为参数传递,因此在编写handleChange ,您可以只对该项目而不是整个数组进行任何操作。

Try this refactored code on CodeSandBox , You have to add keys when iterating Components in React, i've added it, also the Item Component could be function Component since it doesn't handle a state. CodeSandBox上尝试这个重构的代码,在React中迭代Components时必须添加键,我已经添加了它, Item Component也可以是Function Component,因为它不处理状态。

Updated: below is the code in case it wouldn't be available on codesandbox. 更新:下面是代码,以防在codeandbox上不可用。

import React from 'react';
import { render } from 'react-dom';

class App extends React.Component {
  state = {
    items: [],
  }

  componentDidMount() {
    this.setState({
      items: [
        {
          name: 'jacob',
          hair: 'brown',
          sex: 'male',
        }, {
          name: 'hannah',
          hair: 'brown',
          sex: 'female',
        }
      ]
    })
  }

  handleChange = (e) => {
    console.log(e.target.value)
  }

  render() {
    const { items } = this.state;
    return (
      <div>
        {items.length && (
          items.map((item, index) => (
            <div className="row mt-5" key={index}>
              <Item item={item} handleChange={this.handleChange} />
            </div>
          ))
        )
      }
      </div>
    )
  }
}

const Item = ({ item, handleChange }) => (
  <div className="col">
    <div className="mt-5">{item.name}</div>
    <button onClick={handleChange} value={item.name}>Click</button>
  </div>
);

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM