简体   繁体   中英

React: Update UI binded to Array state object

Code works, but is it the right way? All i want is to update the data I retrieved at the page load. Data is in array object.

In the handleChange function, I am replacing the index of the editing employee. Is this the correct way of doing it?

  const [employees, setEmployees] = useState([]);

     const getEmployees = async ()=>{
            const response = await api.get('/employees')
            setEmployees(response.data)
        }
    
        useEffect(()=> {
                getEmployees()
        },[])

    const handleChange =(e, id)=> {
        let editing = employees.filter(e => e.id === id)[0]
        const index = employees.indexOf(editing)        
        editing =  {...editing, [e.target.name]: e.target.value  }
        const empCopy = [...employees]
        empCopy.splice(index,1,editing)
        setEmployees(empCopy)       
    }

 return (
    <div>     
        {
            employees.length > 0 ?
            (employees).map((emp)=> (
                <div class="card" key={emp.id}>
                    <div class="card-body">
                    <div class="form-group">
                            <label for="firstName">First name</label>
                            <input type="text" class="form-control" value={emp.firstName} name="firstName" onChange={(event)=> handleChange(event, emp.id)}/>                       
                        </div>
                        <div class="form-group">
                            <label for="lastName" >Last Name</label>
                            <input type="text" class="form-control" value={emp.lastName} name="lastName" onChange={(event)=> handleChange(event, emp.id)} />                       
                        </div>
                        <div class="form-group">
                            <label for="addressLine">Address</label>
                            <input type="text" class="form-control"   value={emp.addressLine} name="addressLine" onChange={(event)=> handleChange(event, emp.id)}/>                       
                        </div>
                        <div class="form-group">
                            <label for="suburb">Suburb</label>
                            <input type="text" class="form-control"   value={emp.suburb} name="suburb" onChange={(event)=> handleChange(event, emp.id)}/>                       
                        </div>
                        <div class="form-group">
                            <label for="state">State</label>
                            <input type="text" class="form-control"  value={emp.state} name="state" onChange={(event)=> handleChange(event, emp.id)} />                       
                        </div>                  
                        <hr></hr>    
                    </div>
                </div>
                    
            ))
            : "No data"
        
        }
       
    </div>
  )

The map function callback has a second argument , index . So to clean this up a bit you could instead do something like this:

  const [employees, setEmployees] = useState([]);

  const getEmployees = async () => {
    const response = await api.get("/employees");
    setEmployees(response.data);
  };

  useEffect(() => {
    getEmployees();
  }, []);

  const handleChange = (e, index) => {
    let editing = employees[index];
    editing = { ...editing, [e.target.name]: e.target.value };
    
    const empCopy = [...employees];
    empCopy.splice(index, 1, editing);
    setEmployees(empCopy);
  };

  return (
    <div>
      {employees.length > 0
        ? employees.map((emp, index) => (
            <div class="card" key={emp.id}>
              <div class="card-body">
                <div class="form-group">
                  <label for="firstName">First name</label>
                  <input
                    type="text"
                    class="form-control"
                    value={emp.firstName}
                    name="firstName"
                    onChange={(event) => handleChange(event, index)}
                  />
                </div>
                <div class="form-group">
                  <label for="lastName">Last Name</label>
                  <input
                    type="text"
                    class="form-control"
                    value={emp.lastName}
                    name="lastName"
                    onChange={(event) => handleChange(event, index)}
                  />
                </div>
                <div class="form-group">
                  <label for="addressLine">Address</label>
                  <input
                    type="text"
                    class="form-control"
                    value={emp.addressLine}
                    name="addressLine"
                    onChange={(event) => handleChange(event, index)}
                  />
                </div>
                <div class="form-group">
                  <label for="suburb">Suburb</label>
                  <input
                    type="text"
                    class="form-control"
                    value={emp.suburb}
                    name="suburb"
                    onChange={(event) => handleChange(event, index)}
                  />
                </div>
                <div class="form-group">
                  <label for="state">State</label>
                  <input
                    type="text"
                    class="form-control"
                    value={emp.state}
                    name="state"
                    onChange={(event) => handleChange(event, index)}
                  />
                </div>
                <hr></hr>
              </div>
            </div>
          ))
        : "No data"}
    </div>
  );

You can also you .map

handleChange = (e, id) => {
    let updatedEmplyees = employees.map((employee) => {
      if (e.id === id) return { ...employee, [e.target.name]: e.target.value }
      return employee
    })

    setEmployees(updatedEmplyees)
  }

You can do it in a more cleaner and advance syntax . Here is the handleChange method in the form of currying .

 const handleChange = (index) => { return (e) => { let editing = employees[index]; editing = {...editing, [e.target.name]: e.target.value }; const empCopy = [...employees]; empCopy.splice(index, 1, editing); setEmployees(empCopy); }; };
 <input type="text" class="form-control" value={emp.firstName} name="firstName" onChange={handleChange(index)} />
Here is how you can use the method on input field.

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