0

I have a list of buttons and they are multi selectable. when I select the buttons I want to add , it will be added to the array perfectly and turned to blue and when I click on a already selected button it should be get removed from the array and turned to white but it doesn't. Below shows what I tried so far.

The first array (products) is to save the API data. Second one is to save the selected products.

const [products, setProducts] = useState([]);
const [selectedProducts, setselectedProducts] = useState<any>([]);
{products.length !== 0 ? (
    products?.map(
        (item: any, index) => (
            <SButton
                key={item.key}
                label={item.value}
                onClick={() => {
                    selectedProducts(item);
                }}
                isSelected={item.selected === "YES"}
            />
        )
    )
) : (
    <p>No products</p>
)}
function selectedProducts(item:any){
    if(selectedProducts.length !== 0){
        selectedProducts.map((selecteditem:any)=>{
            if(selecteditem.key == item.key ){
                item.selected = "NO";
                setselectedProducts(selectedProducts.filter((item: any )=> item.key !== selecteditem.key))
            }else{
                item.selected = "YES";
                setselectedProducts([...selectedProducts, item]);
            }
        })
    }else{
        setselectedProducts([...selectedProducts, item]);
        item.selected = "YES";
    }
}
1
  • use arr.splice() method to remove the product from the selectedProducts if the the item already selected ... if you want further help then give an code snippet or codepen or any online ide you like Commented Jul 2, 2021 at 17:13

3 Answers 3

1

How about something like this?

const [products, setProducts] = useState([]);
const [selectedProduct, setSelectedProduct] = useState();

{(products.length > 0) ? (
 <Fragment>
   {products.map((item)=>{
     const {key, value, selected } = item;
     return (
       <SButton
        key={key}
        label={value}
        onClick={() => {
          setSelectedProduct(item);
          const newState = !selected;
          products.forEach((p)=>{
            if (p.key === item.key) p.selected = newState;
          });
          setProducts([...products]);
        }}
        isSelected={selected}
       />
     );
   })}
 </Fragment>
): (
 <p>No products</p>
)}
Sign up to request clarification or add additional context in comments.

Comments

1

First, you are using selectedProducts both as function name and name of selected products state.

Second, you should not assign values to item. Use spread operator instead.

Also, you can access the previous state from setState instead of using state directly.

function removeFromSelectedProducts(item: any) {
    // Set selected to 'NO' in products array
    setProducts((prevProducts) =>
        prevProducts.filter((product) =>
            product.key === item.key ? { ...product, selected: 'NO' } : product
        )
    )
    // Remove product from selectedProducts
    setSelectedProducts((prevSelectedProducts) =>
        prevSelectedProducts.filter((product) => product.key !== item.key)
    )
}

function addToSelectedProducts(item: any) {
    // Set selected to 'YES' in products array
    setProducts((prevProducts) =>
        prevProducts.filter((product) =>
            product.key === item.key ? { ...product, selected: 'YES' } : product
        )
    )
    // Add item to selectedProducts
    setSelectedProducts((prevSelectedProducts) => [...prevSelectedProducts, { ...item, selected: 'YES'}])
 }


function selectProduct(item: any) => {
    if (selectedProducts.some((product) => product.key === item.key)) {
        removeFromSelectedProducts(item)
    } else {
        addToSelectedProducts(item)
    }
}

Comments

0

You can simplify this using useReducer hook instead of using separate functions for addition & removal of selected products.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.