简体   繁体   中英

Get value from an input in an array on button click ReactJs

I am relatively new to ReactJs.I am learning react while I am trying to create a real world app. Here is something I cannot solve. I have a repeated component that has one input and one button. everytime the button is clicked, the value of the input will be used in one function.

In Angular I do not have to worry about how to passing those value since in ngFor we can directly assign the value from the ngModel. But there is no such concept in React.

在此处输入图片说明

 betOnTeam = (_id, coins) => {
    return;
};

 {this.teamList.map(team => (
    <div key={team._id}>
       <input type="number" min="100" max="5000"  />
       <button type="button"
               onClick={() => this.betOnTeam(team._id,//value from the 
   input above)}> 
    </div>
  ))}

So basically I Have a function ready to receive an Id and how many coins the user bet. And As we can see from the picture, I have many inputs which should contain the value of how much coins the user put for a specific team. each button will trigger this betOnTeam function and will pass the unique Id of the team, and the number coins the user bet. How can I set states for all thoese teams since they are all dynamic, it could be 5 teams or 100 teams. Is it any way to do it dynamically?

eg user input 5000, when he click the button, the id and the value will be passed into the function betOnTeam.

I hope this clarified my question.

================================== Thanks for all the input from you guys.

I have make it working combine with all your suggestions.

So Here is what I do:

 betOnTeam = (event, id) => {
    console.log(event.target[0].value, id);
    return;
};

 {this.teamList.map(team => (
    <form key={team._id} onSubmit={(e) => this.betOnTeam(e,team._id)}>
       <input type="number" min="100" max="5000"  />
       <button type="submit"> 
    </form >
  ))}

Seems like you're really close. I think this ultimately comes down to how you want to construct your components. There is an easy way to do this (the more React) way, and there is a hard way.

The easy way is to split the mark-up created inside the .map() into its own component. You will have an individual component for each team, thus the state is encapsulated to its own component. By doing this you can effectively keep track of the inputs for each team.

Consider this sandbox for example: https://codesandbox.io/s/dazzling-roentgen-jp8zm

We can create a component for the markup like this:

Team

import React from "react"

class Team extends React.Component {
  state = {
    betValue: 100
  };

  handleOnChange = e => {
    this.setState({
      betValue: e.target.value
    });
  };

  handleOnClick = () => {
    this.props.betOnTeam(this.state.betValue, this.props.id);
  };

  render() {
    const { id } = this.props;
    const { betValue } = this.state;
    return (
      <div key={id}>
        <input
          type="number"
          min="100"
          max="5000"
          value={betValue}
          onChange={this.handleOnChange}
        />
        <button onClick={this.handleOnClick} type="button">
          Bet
        </button>
      </div>
    );
  }
}

export default Team;

So from a purely jsx standpoint, the markup is the same, but now it is contained inside a class-component.

  • Now we can keep track of the inputs in a controlled manner. When we're ready to place the bet, the value is stored in the individual component state.
  • We pass down two properties to each Team component, the team_id and betOnTeam function. The team_id can be accessed using this.props.id and likewise we will pass it into this.props.betOnTeam() when required.

Main Component

import React from "react"
import Team from "./Team"

class App extends React.Component {
  teamList = [
    { team_id: 1, name: "TSM" },
    { team_id: 2, name: "SKT" },
    { team_id: 3, name: "CLG" }
  ];

  betOnTeam = (betValue, teamId) => {
    console.log(betValue);
    console.log(teamId);
  };

  render() {
    return (
      <div>
        {this.teamList.map(team => (
          <Team id={team.team_id} betOnTeam={this.betOnTeam} />
        ))}
      </div>
    );
  }
}

So the .map() renders a Team component for each team and passes in their respective ids and the betOnTeam function as props. When the button inside the component is clicked, we can pass back up the values stored in the Team Component to execute betOnTeam .

onClick={this.betOnTeam(form._id,value)}

Don't execute this.betOnTeam right from the start, you're actually setting the click handler to the returned result of this.betOnTeam(form._id,value) . In React, it's not quite the same as in Angular. For this, you need to set it equal to a function that does that. Like this:

onClick={() => this.betOnTeam(form._id,value)}

Hope this helps.

1. this.betOnTeam = (_id, value) => { ... }

2. constructor(props) { this.betOnTeam.bind(this) }

3. onClick = { () => this.betOnTeam(form._id, value)}

Well if you use onClick = { this.betOnTeam(form._id, value) }, then the code will be executed first, and in betOnTeam function, you will not use 'this' operator.

But if you use the above methods, then you can use 'this' in the function and get the good results.

And your code has some bugs to fix,

{this.array.map(form => (
    <div key={form._id}>
       <input name={`editform{form._id}`} type="number" min="100" max="5000" onChange={(e) => this.changeNumber(e, form._id) }/>
       <button type="button"
               onClick={this.betOnTeam(form._id,value)}> 
    </div>
))}

And in changeNumber function, you should use setState({}) function to set the value to the state, and in betOnTeam function, you can use the state you have already set.

The code must be like this, or otherwise you can use ref but it is not formally encouraged to use ref. Totally, you should use ControlledComponent. That's the target.

I hope you to solve the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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