Home > Software engineering >  map and count quantity in react
map and count quantity in react

Time:11-28

I have a view with the list of articles the user add to basket.

In each article i have an increment/decrement button to edit the quantity. The increment/decrement buttons are working because it's adding in my array a new Object every time my user change the quantity

For now, i just have a " " and "-" button, but i would like to see the number of the quantity

What i was thinking about :

  • get all the articles list and count the duplicate in a useEffect (every time the articles list is changing)
  • set the article id and quantity with useState object

What is the best way to count individual quantity of each articles ?

here my component with the articles map and increment/decrement buttons

   import React from 'react';
    import { Table } from 'react-bootstrap';
    import { useFieldArray } from 'react-hook-form';
    
    export const ListArticle = ({ watch, control }) => {
      const list = watch('Articles');

      //listWithoutDuplicates is because i just want to see once my articles even if the quantity is more than 1
      const listWithoutDuplicates = list?.filter(
        (ele, ind) => ind === list?.findIndex((elem) => elem.name === ele.name)
      );
    
      const { append, remove } = useFieldArray({
        control,
        name: 'Articles',
      });
    
      const increment = (oneArticle) => {
        append(oneArticle);
      };
    
      const decrement = (oneArticle) => {
        remove(oneArticle);
      };
    
     
      return (
        <>
          <Table responsive>
            <thead>
              <tr>
                <th> Name </th>
                <th> Color</th>
                <th> Quantity </th>
              </tr>
            </thead>
            <tbody>
              {listWithoutDuplicates?.map((oneArticle, index) => {
                return (
                  <tr key={index}>
                    <td>
                      <span>{oneArticle?.name}</span>
                    </td>
                    <td>
                      <span>{oneArticle?.color}</span>
                    </td>
                    <td>
                      <button type="button" onClick={() => decrement(oneArticle)}>
                        -
                      </button>
                       <p> HERE MY QUANTITY </p>
                      <button type="button" onClick={() => increment(oneArticle)}>
                         
                      </button>
              
                    </td>   
                  </tr>
                );
              })}
            </tbody> 
          </Table>
        </>
      );
    };

CodePudding user response:

Why you just don't hold the quantity field for each article instead of storing multiple articles ?

const { append, remove, update } = useFieldArray({
  control,
  name: 'Articles',
});  

const increment = (index) => {
  const oneArticle = {...list[index]};
  oneArticle.quantity  = 1;
  update(index, oneArticle);
};
    
const decrement = (index) => {
  const oneArticle = {...list[index]};
  // It's the last quantity of the article so we should remove it from the list.
  if(oneArticle.quantity === 1) {
    remove(index);
  // It's not the last quantity of the article so we should decrease the quantity.
  } else {
    oneArticle.quantity -= 1;
    update(index, oneArticle);
  }
};

And then just loop through the list data and there is no need to use listWithoutDuplicates anymore.

<tbody>
  {list?.map((oneArticle, index) => {
    return (
      <tr key={index}>
        <td>
          <span>{oneArticle?.name}</span>
        </td>
        <td>
          <span>{oneArticle?.color}</span>
        </td>
        <td>
          <span>{oneArticle?.quantity}</span>
        </td>
        <td>
          <button type="button" onClick={() => decrement(index)}>
            -
          </button>
          <button type="button" onClick={() => increment(index)}>
             
          </button>
        </td>   
      </tr>
    )
  })}
</tbody> 

And another point is that remove gets index or array of indexes not the object.

CodePudding user response:

use Like this...

  import React,{useState} from 'react';
    import { Table } from 'react-bootstrap';
    import { useFieldArray } from 'react-hook-form';
    
    export const ListArticle = ({ watch, control }) => {
      const [list, setList] = useState(watch('Articles'));
    
      //listWithoutDuplicates is because i just want to see once my articles even if the quantity is more than 1
      //const listWithoutDuplicates = list?.filter(
       // (ele, ind) => ind === list?.findIndex((elem) => elem.name === ele.name)
     // );
    
      const { append, remove } = useFieldArray({
        control,
        name: 'Articles',
      });
    
      const increment = (index) => {
       //append(oneArticle);
    let newList =list;
    newList[index].quantity =(newList[index].quantity || 0)  1
    setList(newList)
      };
    
      const decrement = (index) => {
        //remove(oneArticle);
    let newList =list;
    newList[index].quantity =(newList[index].quantity || 0) -1
    setList(newList)
      };
    
     
      return (
        <>
          <Table responsive>
            <thead>
              <tr>
                <th> Name </th>
                <th> Color</th>
                <th> Quantity </th>
              </tr>
            </thead>
            <tbody>
              {list?.map((oneArticle, index) => {
                return (
                  <tr key={index}>
                    <td>
                      <span>{oneArticle?.name}</span>
                    </td>
                    <td>
                      <span>{oneArticle?.color}</span>
                    </td>
                    <td>
                      <button type="button" onClick={() => decrement(index)}>
                        -
                      </button>
                       <p>{oneArticle.quantity || 0}</p>
                      <button type="button" onClick={() => increment(index)}>
                         
                      </button>
              
                    </td>   
                  </tr>
                );
              })}
            </tbody> 
          </Table>
        </>
      );
};

I hope this will help you!

  • Related