skip to Main Content

I have two tables, one is All Products table and other is Selected Product Table. I’m using jsonplaceholder/users for demo purpose.
The All products table has a search bar which shows all the data from the API.

Each data field in the All product table have a checkbox input. When the checkbox is selected, I want that specific data to be reflected in the Selected Product Table.

But the "checked" useState() gives a empty [] instead of the selected field data.
I want this data to be reflected on the Selected Products table.

useState hooks and functions:

const [checked, setChecked] = useState([])
const [input, setInput] = useState("");
const [results, setResults] = useState([])
const [apiData, setApiData] = useState([]);

const handleAPI = async (url) => {
    try {
        let fetchData = await fetch("https://jsonplaceholder.typicode.com/users");
        let data = await fetchData.json();
        setApiData(data);

        const result = data.filter((user) => {
            return (
                url &&
                user &&
                user.name &&
                user.name.toLowerCase().includes(url)

            )
        })
        // console.log(result)
        setResults(result)
    } catch (err) {
        console.log(err)
    }
}

useEffect(() => {
    handleAPI()
}, [])


const handleSearch = (value) => {
    setInput(value);
    handleAPI(value);
}

const handleCheck = (id) => {
    setChecked(prevState => [...prevState, id])
    console.log(checked)
}

const handleDelete = (product) => {
    const deleteData = checked.filter((item) => 
        item.id !== product.id);
    setChecked(deleteData)       

}

All Product Table:

<table className='w-full h-max'>
 <tr>
   <th className='flex items-center gap-3 text-left' >
     <img src={dashboardCheckbox} alt="checkbox" />
     <p className='text-xs text-[#667085] font-medium'>Product</p>
   </th>

   <th className='text-left'>
     <p className='text-xs text-[#667085] font-medium'>Price</p>
   </th>

   <th className='text-left'>
      <p className='text-xs text-[#667085] font-medium'>Status</p>
   </th>
 </tr>

 {results.map((res, id) => (
   <tr key={id} >
     <td className='flex items-center py-4'>
       <input onClick={(id) => handleCheck(res.id)} type="checkbox" className='w-[19px] h-[19px] mr-[0.8rem] cursor-pointer' />
       <div className='flex items-center gap-3'>
         <img src={avatar} alt="" />
       <div>
       <div className='text-sm font-medium'>{res.name}</div>
         <div className='text-sm text-[#667085]'>{res.company.name}</div>
       </div>
      </div>
     </td>
     <td className='text-sm'>₹160</td>
     <td className='text-xs'>• Not Available</td>
    </tr>

Selected Product Table:

<table className='w-full h-max'>
  <tr className=''>
    <th className='flex items-center gap-3 text-left' >
     <p className='text-xs text-[#667085] font-medium'>Product</p>
    </th>

    <th className='text-left'>
      <p className='text-xs text-[#667085] font-medium'>Price</p>
    </th>

   </tr>

   {checked.map((r, id) => (
     <tr key={id}>
       <td className='flex items-center py-4'>
       <div className='flex items-center gap-3'>
         <img src={avatar} alt="" />
        <div>
         <div className='text-sm font-medium'>{r.name}</div>
         <div className='text-sm text-[#667085]'>seller</div>
        </div>
       </div>
      </td>

      <td className='text-sm'>₹160</td>
      <td className='text-sm cursor-pointer' onClick={(id) => handleDelete(id)}>Delete</td>
    </tr>
                                    
 )
 )}

2

Answers


  1. Your code is adding the id of the selected product to the checked state, which is an array of IDs. You need to store the entire data of the selected products to display them in the Selected Products table.

    const [checked, setChecked] = useState([]);
    const [input, setInput] = useState("");
    const [results, setResults] = useState([]);
    const [selectedProducts, setSelectedProducts] = useState([]);
    
    const handleCheck = (product) => {
      // Check if the product is already in the checked list
      const isChecked = checked.some((item) => item.id === product.id);
    
      if (!isChecked) {
        setChecked((prevState) => [...prevState, product.id]);
        setSelectedProducts((prevState) => [...prevState, product]);
      } else {
        // Remove product from checked list and selected products
        const updatedChecked = checked.filter((item) => item.id !== product.id);
        setChecked(updatedChecked);
        const updatedSelectedProducts = selectedProducts.filter(
          (item) => item.id !== product.id
        );
        setSelectedProducts(updatedSelectedProducts);
      }
    };
    

    Also Update the delete function as well

    const handleDelete = (product) => {
      const updatedChecked = checked.filter((item) => item.id !== product.id);
      setChecked(updatedChecked);
      const updatedSelectedProducts = selectedProducts.filter(
        (item) => item.id !== product.id
      );
      setSelectedProducts(updatedSelectedProducts);
    };
    

    and The All Table send the whole res not only res.id

    <td className='flex items-center py-4'>
           <input onClick={(id) => handleCheck(res)} type="checkbox" className='w-[19px] h-[19px] mr-[0.8rem] cursor-pointer' />
           <div className='flex items-center gap-3'>
             <img src={avatar} alt="" />
           <div>
           <div className='text-sm font-medium'>{res.name}</div>
             <div className='text-sm text-[#667085]'>{res.company.name}</div>
           </div>
          </div>
         </td>
    

    I have created an extra state called [selectedProducts, setSelectedProducts]. The checked state for the IDs of the selected products and selectedProducts for the actual data of the selected products. When a checkbox is clicked, it checks if the product is already in the checked list. If not, it adds the product ID to the checked array and the entire product data to the selectedProducts array. If the product is already checked, it removes the product from both arrays.

    Ensure that you use selectedProducts to render the Selected Products table to display the selected product data. This way, you’ll reflect the selected products based on the checkbox selection in the All Products table.

    Login or Signup to reply.
  2. I have fixed your example by modifying source code:

    Working codesandbox Demo link: Link

    Note: Please look the codesandbox link to know more about MUI components. I have used Spinner directly from there. You can also create your custom one.

    Full code:

    import React, { useState, useEffect } from "react";
    import axios from "axios";
    import CircularProgress from "@mui/material/CircularProgress";
    import Box from "@mui/material/Box";
    
    const Checkboxes = () => {
      const [checked, setChecked] = useState([]);
      const [data, setApiData] = useState([]);
      const [spinner, setSpinner] = useState(true);
    
      const handleAPI = async () => {
        try {
          const response = await axios.get(
            "https://jsonplaceholder.typicode.com/users",
          );
          setApiData(response.data);
          setSpinner(false);
        } catch (err) {
          console.log(err);
          setSpinner(false);
        }
      };
    
      useEffect(() => {
        handleAPI();
      }, []);
    
      const handleCheck = (id) => {
        const isChecked = checked.includes(id);
        if (isChecked) {
          setChecked(checked.filter((itemId) => itemId !== id));
        } else {
          setChecked([...checked, id]);
        }
      };
    
      const handleDelete = (id) => {
        const updatedChecked = checked.filter((itemId) => itemId !== id);
        setChecked(updatedChecked);
      };
    
      if (spinner) {
        return (
          <Box
            sx={{
              display: "flex",
              justifyContent: "center",
              alignItems: "center",
              height: "100vh",
            }}
          >
            <CircularProgress />
          </Box>
        );
      }
    
      return (
        <div>
          <div className="App">
            <h1>All product table</h1>
            <table className="w-full h-max">
              <thead>
                <tr>
                  <th className="flex items-center gap-3 text-left">
                    <p className="text-xs text-[#667085] font-medium">Checkbox</p>
                  </th>
                  <th className="flex items-center gap-3 text-left">
                    <p className="text-xs text-[#667085] font-medium">Product</p>
                  </th>
                  <th className="text-left">
                    <p className="text-xs text-[#667085] font-medium">Price</p>
                  </th>
    
                  <th className="text-left">
                    <p className="text-xs text-[#667085] font-medium">Status</p>
                  </th>
                </tr>
              </thead>
              <tbody>
                {data.map((res) => (
                  <tr key={res.id}>
                    <td className="flex items-center py-4">
                      <div style={{ display: "flex" }}>
                        <input
                          onChange={() => handleCheck(res.id)}
                          checked={checked.includes(res.id)}
                          type="checkbox"
                          className="w-[19px] h-[19px] mr-[0.8rem] cursor-pointer"
                        />
                        <div className="flex items-center gap-3">
                          <div>
                            <div className="text-sm font-medium">{res.name}</div>
                          </div>
                        </div>
                      </div>
                    </td>
    
                    <td>
                      <div className="flex items-center gap-3">
                        <div>
                          <div className="text-sm font-medium">
                            {res.company.name}
                          </div>
                        </div>
                      </div>
                    </td>
    
                    <td>
                      <div className="flex items-center gap-3">
                        <div>
                          <div className="text-sm font-medium">₹160</div>
                        </div>
                      </div>
                    </td>
    
                    <td>
                      <div className="flex items-center gap-3">
                        <div>
                          <div className="text-sm font-medium">
                            &#8226; Not Available
                          </div>
                        </div>
                      </div>
                    </td>
                  </tr>
                ))}
              </tbody>
            </table>
          </div>
    
          <div className="App">
            <h1>Selected Product Table</h1>
            <table className="w-full h-max">
              <thead>
                <tr>
                  <th className="flex items-center gap-3 text-left">
                    <p className="text-xs text-[#667085] font-medium">Product</p>
                  </th>
                </tr>
              </thead>
              <tbody>
                {checked.map((id, idx) => {
                  const selectedProduct = data.find((item) => item.id === id);
                  return (
                    <tr key={idx}>
                      <td className="flex items-center py-4">
                        <div className="flex items-center gap-3">
                          <div>
                            <div className="text-sm font-medium">
                              {selectedProduct.name}
                            </div>
                          </div>
                        </div>
                      </td>
                      <td className="text-sm cursor-pointer">
                        <button onClick={() => handleDelete(id)}> Delete</button>
                      </td>
                    </tr>
                  );
                })}
              </tbody>
            </table>
          </div>
        </div>
      );
    };
    
    export default Checkboxes;
    

    I have added spinner while fetching data from an API to store empty value in state. Besides that, I have modified logic too.

    Look at it and let me know, If you’ve any questions 🙂

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search