Home > Back-end >  How to handle unknown number of state variables in React.js?
How to handle unknown number of state variables in React.js?

Time:05-10

I am getting data from server. I don't know exactly how many items in the api. Therefore, I am using map method in html. Below is the return part.

   if (loading) {
    return (
      <div>
        <div>
          <Header />
          <Sidebar />
        </div>
        <h1>LOADING ...</h1>
      </div>
    );
  }
  if (error) console.log(error);
  return (
    <div>
      <div>
        <Header />
        <Sidebar />
        <h1>Menu Edit Page</h1>
        {edit === false ? (
          <div>
            <table>
              <tbody>
            {
              data?.map((item, index) => (
                <tr>
                  <td>Name: </td>
                  <td>{item?.name}</td>
                  {/* Full_Name: { item.name }, 
                User_Email: { item.email }  */}
                </tr>
              ))
            }
            </tbody>
            </table>
            <Button onClick={() => editMenu()}>edit</Button>
          </div>
        ) : (
          <div>
            <table>
              <tbody>
            {
              data?.map((item, index) => (
                <tr>
                  <td>Name: </td>
                  <input
                  type="text"
                  required="required"
                  placeholder="Edit menu item"
                  name="age"
                  defaultValue={item?.name}
                  onChange={() => itemChange(item?.class, item?.id)}
                  >
                  </input>
                  {/* {item?.name} */}
                  {/* Full_Name: { item.name }, 
                User_Email: { item.email }  */}
                </tr>
              ))
            }
            </tbody>
            </table>
            <Button onClick={() => saveMenu()}>save</Button>
          </div>
        )}
      </div>
    </div>
  )

When i use input tag for objects, I need to manipulate them when i click the button. However, I dont know how many objects, so I cannot use state variables. Moreover, i need to know information from object itself when i change the object. Whole code is below.

 import React, { useState } from 'react'
import Header from "../Components/common/header/header";
import Sidebar from "../Components/common/sidebar/Sidebar";/// IGNORE THIS PAGE
import useFetch from './useFetch';
import { Button } from 'antd';
function MenuEditer() {
  const [newItem, setNewItem] = useState("")
  const [edit, setEdit] = useState(false);
  const [buttonPressed, setButtonPressed] = useState(false);
  const { data, loading, error } = useFetch("http://localhost:3001/category/deneme");

  const itemChange = async (clss, id) => {
    alert("beginning of the func");
    // while(!buttonPressed);
    // alert("button pressed");
    // if(clss === "category"){

    // }
    // if(clss === "item"){

    // }
  }
  const saveMenu = async () => {
    setButtonPressed(true);
    setEdit(false);
  }
  const editMenu = async () => {
    setEdit(true);
  }
  if (loading) {
    return (
      <div>
        <div>
          <Header />
          <Sidebar />
        </div>
        <h1>LOADING ...</h1>
      </div>
    );
  }
  if (error) console.log(error);
  return (
    <div>
      <div>
        <Header />
        <Sidebar />
        <h1>Menu Edit Page</h1>
        {edit === false ? (
          <div>
            <table>
              <tbody>
            {
              data?.map((item, index) => (
                <tr>
                  <td>Name: </td>
                  <td>{item?.name}</td>
                  {/* Full_Name: { item.name }, 
                User_Email: { item.email }  */}
                </tr>
              ))
            }
            </tbody>
            </table>
            <Button onClick={() => editMenu()}>edit</Button>
          </div>
        ) : (
          <div>
            <table>
              <tbody>
            {
              data?.map((item, index) => (
                <tr>
                  <td>Name: </td>
                  <input
                  type="text"
                  required="required"
                  placeholder="Edit menu item"
                  name="age"
                  defaultValue={item?.name}
                  onChange={() => itemChange(item?.class, item?.id)}
                  >
                  </input>
                  {/* {item?.name} */}
                  {/* Full_Name: { item.name }, 
                User_Email: { item.email }  */}
                </tr>
              ))
            }
            </tbody>
            </table>
            <Button onClick={() => saveMenu()}>save</Button>
          </div>
        )}
      </div>
    </div>
  )
}

export default MenuEditer;

How can I reach object itself from the array, or use useState hook without knowing the length of data? OR, can i write statements of function in onClick attribute? OR, can i use anything else for input form for specifically reach the object and updated string ? The issue may not be clear but I would be very appreciated to any idea. Thanks!

CodePudding user response:

you can use an object to handle the inputs data

at first use useEffect to set the initial values of the state

Note make sure that the property name for the HTML input is the same as the one that comes form the API the

const [formData, setFormData] = useState({})

useEffect(() => {
  const copy = formData
  data.forEach((item,index)=> {
   copy["item"   index] = {name: item.name, email: item.email}

    setFormData(copy)
})
}, [])

then allow the event handler to automatically handle the change

const itemChange = (event, index) {
  const copy = formData
  const changedItem = copy["item"   index]
  changedItem[event.target.name] = event.target.value

 setFormData(copy)
  
}

in the input element

<input
     type="text"
     required={true}
     placeholder="Edit menu item"
     name="age"  // make sure the name is same as the property name that comes form the api
     value={formData["item"   index].age}
     onChange={(e) => itemChange(e, index)}
 />
  • Related