简体   繁体   English

将点击的项目添加到 React 中的新数组

[英]Adding clicked items to new array in React

I am making API calls and rendering different components within an object.我正在调用 API 并在对象中呈现不同的组件。 One of those is illustrated below:其中之一如下图所示:

class Bases extends Component {
    constructor() {
        super();

        this.state = {
            'basesObject': {}
        }
    }

    componentDidMount() {
        this.getBases();
    }

    getBases() {
        fetch('http://localhost:4000/cupcakes/bases')
        .then(results => results.json())
        .then(results => this.setState({'basesObject': results}))
    }

    render() {

        let {basesObject} = this.state;  
        let {bases} = basesObject; 

        console.log(bases); 
        //FALSY values: undefined, null, NaN, 0, false, ""

        return (

            <div>
                {bases && bases.map(item =>
                    <button key={item.key} className="boxes">
                        {/* <p>{item.key}</p> */}
                        <p>{item.name}</p>
                        <p>${item.price}.00</p>
                        {/* <p>{item.ingredients}</p> */}
                    </button>
            )}
           </div>
        )
    }
}

The above renders a set of buttons.上面呈现了一组按钮。 All my components look basically the same.我所有的组件看起来基本相同。

I render my components here:我在这里渲染我的组件:

class App extends Component {
  state = {
    ordersArray: []
  }

  render() {
    return (
      <div>
        <h1>Bases</h1>
        <Bases />
        <h1>Frostings</h1>
        <Frostings />
        <h1>Toppings</h1>
        <Toppings />
      </div>
    );
  }
}

I need to figure out the simplest way to, when a button is clicked by the user, add the key of each clicked element to a new array and I am not sure where to start.我需要找出最简单的方法,当用户单击按钮时,将每个单击元素的键添加到新数组中,但我不确定从哪里开始。 The user must select one of each, but is allowed to select as many toppings as they want.用户必须选择每一种,但可以根据需要选择任意数量的浇头。

在此处输入图片说明

Try this尝试这个

We can use the same component for all categories.我们可以对所有类别使用相同的组件。 All the data is handled by the parent (stateless component).所有数据都由父级(无状态组件)处理。

function Buttons({ list, handleClick }) {
  return (
    <div>
      {list.map(({ key, name, price, isSelected }) => (
        <button
          className={isSelected ? "active" : ""}
          key={key}
          onClick={() => handleClick(key)}
        >
          <span>{name}</span>
          <span>${price}</span>
        </button>
      ))}
    </div>
  );
}

Fetch data in App component, pass the data and handleClick method into Buttons .App组件中获取数据,将数据和 handleClick 方法传递给Buttons

class App extends Component {
  state = {
    basesArray: [],
    toppingsArray: []
  };

  componentDidMount() {
    // Get bases and toppings list, and add isSelected attribute with default value false
    this.setState({
      basesArray: [
        { key: "bases1", name: "bases1", price: 1, isSelected: false },
        { key: "bases2", name: "bases2", price: 2, isSelected: false },
        { key: "bases3", name: "bases3", price: 3, isSelected: false }
      ],
      toppingsArray: [
        { key: "topping1", name: "topping1", price: 1, isSelected: false },
        { key: "topping2", name: "topping2", price: 2, isSelected: false },
        { key: "topping3", name: "topping3", price: 3, isSelected: false }
      ]
    });
  }

  // for single selected category
  handleSingleSelected = type => key => {
    this.setState(state => ({
      [type]: state[type].map(item => ({
        ...item,
        isSelected: item.key === key
      }))
    }));
  };

  // for multiple selected category
  handleMultiSelected = type => key => {
    this.setState(state => ({
      [type]: state[type].map(item => {
        if (item.key === key) {
          return {
            ...item,
            isSelected: !item.isSelected
          };
        }
        return item;
      })
    }));
  };

  // get final selected item
  handleSubmit = () => {
    const { basesArray, toppingsArray } = this.state;
    const selectedBases = basesArray.filter(({ isSelected }) => isSelected);
    const selectedToppings = toppingsArray.filter(({ isSelected }) => isSelected);

    // submit the result here
  }

  render() {
    const { basesArray, toppingsArray } = this.state;

    return (
      <div>
        <h1>Bases</h1>
        <Buttons
          list={basesArray}
          handleClick={this.handleSingleSelected("basesArray")}
        />
        <h1>Toppings</h1>
        <Buttons
          list={toppingsArray}
          handleClick={this.handleMultiSelected("toppingsArray")}
        />
      </div>
    );
  }
}

export default App;

CSS CSS

button {
  margin: 5px;
}
button.active {
  background: lightblue;
}

I think the following example would be a good start for your case.我认为以下示例将是您案例的良好开端。

Define a handleClick function where you can set state with setState as the following:定义一个handleClick函数,您可以在其中使用setState设置状态,如下所示:

handleClick(item) {
  this.setState(prevState => {
    return {
       ...prevState,
       clickedItems: [...prevState.clickedItems, item.key]
    };
  });
}

Create an array called clickedItems in constructor for state and bind handleClick :在构造函数中为state创建一个名为clickedItems的数组并绑定handleClick

constructor() {
   super();
   this.state = {
      basesObject: {},
      clickedItems: [],
   }

   this.handleClick = this.handleClick.bind(this);
}

You need to add a onClick={() => handleClick(item)} handler for onClick :您需要添加一个onClick={() => handleClick(item)}处理程序onClick

<button key={item.key} className="boxes" onClick={() => handleClick(item)}>
   {/* <p>{item.key}</p> */}
   <p>{item.name}</p>
   <p>${item.price}.00</p>
   {/* <p>{item.ingredients}</p> */}
</button>

I hope that helps!我希望这有帮助!

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

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