简体   繁体   中英

React.js not incrementing after function call in onclick

I need to build a table in order to organize some data. I'm using the "onclick" function in order to call a separate function, which is supposed to increment a state variable up by one. My Chrome Devtools isn't giving me any errors but also isn't updating the stock variable. I'm not sure how to get the state to update and display. Here's my source code:

class App extends React.Component {
    constructor(props) {
        super(props);

        this.state = {
            cars: [
                {
                    manufacturer: "Toyota",
                    model: "Rav4",
                    year: 2008,
                    stock: 3,
                    price: 8500
                },
    
                {
                    manufacturer: "Toyota",
                    model: "Camry",
                    year: 2009,
                    stock: 2,
                    price: 6500
                },
    
                {
                    manufacturer: "Toyota",
                    model: "Tacoma",
                    year: 2016,
                    stock: 1,
                    price: 22000
                },
    
                {
                    manufacturer: "BMW",
                    model: "i3",
                    year: 2012,
                    stock: 5,
                    price: 12000
                },
    
            ]
        };
        this.renderCar = this.renderRow.bind(this);
        this.handleClick = this.handleClick.bind(this);
    }

    handleClick() {
        this.setState(() => {
            return {stock: this.stock + 1}
        })
    }

    renderRow(car, index) {
        return (
            <tr key={index}>
                <td key={car.manufacturer}>{car.manufacturer}</td>
                <td key={car.model}>{car.model}</td>
                <td key={car.year}>{car.year}</td>
                <td key={car.stock}>{car.stock}</td>
                <td key={car.price}>${car.price}.00</td>
                <td key={index}><input type="button" onClick={car.handleClick} value="Increment" /></td>
            </tr>
        )
    }

    render() {
        return (
            <div>
            <table>
                <thead>
                <tr>
                    <th>Manufacturer</th>
                    <th>Model</th>
                    <th>Year</th>
                    <th>Stock</th>
                    <th>Price</th>
                    <th>Option</th>
                </tr>
                </thead>
                <tbody>
                    {this.state.cars.map(this.renderRow)}
                </tbody>
            </table>
            </div>
        );
    };
}

ReactDOM.render(<App />, document.getElementById("app"))

I'd make a separate component for the row, so that you can easily update that component to increment the stock value in state:

 class App extends React.Component { constructor(props) { super(props); this.state = { cars: [ { manufacturer: "Toyota", model: "Rav4", year: 2008, stock: 3, price: 8500 }, { manufacturer: "Toyota", model: "Camry", year: 2009, stock: 2, price: 6500 }, { manufacturer: "Toyota", model: "Tacoma", year: 2016, stock: 1, price: 22000 }, { manufacturer: "BMW", model: "i3", year: 2012, stock: 5, price: 12000 }, ] }; } render() { return ( <div> <table> <thead> <tr> <th>Manufacturer</th> <th>Model</th> <th>Year</th> <th>Stock</th> <th>Price</th> <th>Option</th> </tr> </thead> <tbody> {this.state.cars.map( (car, i) => <Row car={car} key={i} /> )} </tbody> </table> </div> ); }; } const Row = ({ car }) => { const [stock, setStock] = React.useState(car.stock); return ( <tr> <td>{car.manufacturer}</td> <td>{car.model}</td> <td>{car.year}</td> <td>{stock}</td> <td>${car.price}.00</td> <td><input type="button" onClick={() => setStock(stock + 1)} value="Increment" /></td> </tr> ); } ReactDOM.render(<App />, document.getElementById("app"))
 <script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script> <script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script> <div id='app'></div>

You could put it all in one component if you had to, but it'd be a bit cumbersome. While rendering, you'd have to keep track of the render index of a row and pass that along to the click handler, then immutably update the stock property in the state array at that index. A separate component is easier.

   handleClick(e){
      const index = Number(e.currentTarget.value);
      this.setState(this.state.cars.map(car, i)=> {
        return i === index ? {...car, stock: car.stock + 1}: car 
      })
   }
 
   renderRow(){
    ....
       <input type="button" onClick={this.handleClick} value={index} />
    ...
   }

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