简体   繁体   中英

React UseState()

I am trying to change the state of the product quantities whenever someone clicks on a button (Increment/decrement). But somehow it is not incrementing the quantity here. When I click on increment button, it changes the quantity for the first item. When I click on second item increment button, it reset the quantity for first item and make changes to the second one. [1]: https://i.stack.imgur.com/fifeQ.png

Here's my code

**App.js**

function App() {

let [productList, setProductList] = useState([]);

productList = [
{
      id: 0,
      prodName: "iPhone X",
      type: "Mobile",
      price: "80000",
      quantity: 0,
},
{
      id: 1,
      prodName: "iPhone 11",
      type: "Mobile",
      price: "120000",
      quantity: 0,
},
{
      id: 2,
      prodName: "iPhone 12",
      type: "Mobile",
      price: "180000",
      quantity: 0,

}];

const incrementQuantity = (index) => {
    let newProductList = [...productList];
    newProductList[index].quantity++;
    setProductList(newProductList);
    console.log(newProductList); 
}
return (
    <div className="App">
      
      <Header heading="Simple Cart project" />
      <Mediator list={productList} incrementQuantity={incrementQuantity} />
      {/* list is the property name which you are passing to different component */}
    </div>
  );
}

export default App;
    

**Mediator.js**
    
function Mediator(props) {
    return (
            props.list.map((product, index) => {

                return <ProductList productList={product} key={index} incrementQuantity = {props.incrementQuantity} index={index}/>
            })
    );
}
export default Mediator;
    
    
**ProductList.js**
    
function ProductList(props) {
    console.log("inside product list")
    console.log(props);

    return (
        <div className="row">
            <div className="col-5">
                <h2>{props.productList.prodName} </h2> <span className="price-column"><Chip label={props.productList.price} color="success" />₹ <br />
                </span> <br />
            </div>
            <div className="col-3">
                <ButtonGroup size="small" color="secondary" aria-label="small button group">
                    <Button className="btn-decrease">-</Button>
                   
                    <Box
                        component="div"
                        sx={{
                            display: 'inline',
                            p: 1,
                            m: 1,
                            bgcolor: 'background.paper',
}}
                    >
                        {props.productList.quantity}
                    </Box>

                    <Button className="btn-increase"
                        onClick={() => { props.incrementQuantity(props.index) }}

                    >+</Button>
                </ButtonGroup>
            </div>
            <div className="col-4">
                <span><h4>Total Cart Price: </h4>{props.productList.quantity * props.productList.price}</span>
            </div>
        </div>

    );
}

export default ProductList;

Because on every render the very first thing you do is locally modify the variable holding the state to a hard-coded list of initial values. Don't mutate state like that.

Instead, set that hard-coded initial value as the initial default for the useState hook:

let [productList, setProductList] = useState([
{
      id: 0,
      prodName: "iPhone X",
      type: "Mobile",
      price: "80000",
      quantity: 0,
},
{
      id: 1,
      prodName: "iPhone 11",
      type: "Mobile",
      price: "120000",
      quantity: 0,
},
{
      id: 2,
      prodName: "iPhone 12",
      type: "Mobile",
      price: "180000",
      quantity: 0,

}]);

Never directly modify or replace productList , only use setProductList to update it.

David's answer is correct but there's another problem with your code in that you need to get the previous productList state in your setProductList if you want to modify productList to be safe in case anything else (like a different incrementQuantity call) has modified it.

function App() {

  const [productList, setProductList] = useState([
    {
      id: 0,
      prodName: "iPhone X",
      type: "Mobile",
      price: "80000",
      quantity: 0,
    },
    {
      id: 1,
      prodName: "iPhone 11",
      type: "Mobile",
      price: "120000",
      quantity: 0,
    },
    {
      id: 2,
      prodName: "iPhone 12",
      type: "Mobile",
      price: "180000",
      quantity: 0,

    }]);

  const incrementQuantity = (index) => {
    setProductList((prodList) => {
      prodList[index].quantity++;
      return prodList;
    });
  }
  
  ...
}

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