Home > Mobile >  How to update a useState which has an array, inside this array I have objects this objects will upda
How to update a useState which has an array, inside this array I have objects this objects will upda

Time:06-11

   const [fvalues,setFvalues]=useState(data.map((ele,id)=>{
    return(
    {mobile:'',age:'',emailId:'',destinationAddress:'',destinationPin:''}
    );
}));

I want to update these objects when there is a change in input tag values

let handleChange = (e)=>{
    let {name,value}=e.target;
    data.map((ele,id)=>{
        // return setFvalues({ ...fvalues[id], [name]: value });
        setFvalues(fvalues[id].name)
    })
    // setFvalues(fvalues[0].name=value)
    console.log(name,value);
}

but this logic is not working

I have mapped forms and want to submit all the forms with one submit button, I want to update the input values which is entered by the users

{datas.map((ele, id) => {
                    let val = id   1;
                    return (
                        <>
                            <Box key={id}>
                                {/* <HealthAndContactPass key={id} fun={handelSubmit} psName={ele?.psName} address={ele?.address} /> */}
                                {/* <HealthAndContactPassForm errors={errors} handleSubmit={handleSubmit} register={register} id={id} psName={ele?.psName} address={ele?.address} onSubmit={onSubmit}/> */}
                                <Typography className={styles.psName}>{ele.psName}</Typography>
                                <Box className={styles.white_box}>
                                    <Box className={styles.form_flex}>
                                        <Box className={styles.mobile}>
                                            <Select className={classes.select} name='countryCode' defaultValue={' 91'} value={code} {...register("code")}>
                                                <MenuItem className={styles.code_id} value={' 91'}> 91</MenuItem>
                                                <MenuItem className={styles.code_id} value={' 25'}> 25</MenuItem>
                                                <MenuItem className={styles.code_id} value={' 12'}> 12</MenuItem>
                                                <MenuItem className={styles.code_id} value={' 13'}> 13</MenuItem>
                                            </Select>
                                            <TextField helperText={ferrors?.mobile}  value={fvalues[id].mobile} name="mobile" classes={{ root: classes.textField }} InputProps={{ className: classes.textField }} label="Mobile Number" variant="outlined" onChange={handleChange} />
                                            <TextField value={fvalues[id].emailId}  name="emailId" classes={{ root: classes.textField }} InputProps={{ className: classes.textField }} label="Email Id" variant="outlined" onChange={handleChange}  />
                                            <TextField value={fvalues[id].age}  name="age" classes={{ root: classes.textField }} InputProps={{ className: classes.textField }} label="age" variant="outlined" onChange={handleChange}  />
                                        </Box>
                                    </Box>
                                    <Box className={styles.form_flex2}>
                                        <TextField value={fvalues[id].destinationAddress} name="destinationAddress" classes={{ root: classes.textField }} InputProps={{ className: classes.textField }} label="destinationAddress" variant="outlined" onChange={handleChange}  />
                                        <TextField value={fvalues[id].destinationPin} name="destinationPin" classes={{ root: classes.textField }} InputProps={{ className: classes.textField }} label="destinationPin" variant="outlined" onChange={handleChange}  />
                                    </Box>
                                    <Box className={styles.hr}></Box>
                                    {id===0?(
                                        <Box className={styles.addres}>
                                        <ThemeProvider theme={theme}>
                                            <Checkbox className={classes.check} {...label} />
                                        </ThemeProvider>
                                        <Typography className={styles.selectAdd}>Select same address for all</Typography>
                                    </Box>):null
                                    }
                                </Box>
                            </Box>
                        </>
                    )
                })}

CodePudding user response:

In this case you don't "update" the state array per se, rather you create a clone of the state array then modify the values you want and set the state to be this cloned array. I wasn't quite sure what exactly you wanted to do to the array, but see the general example below:

const [state, setState] = useState([{mobile:'',age:'',emailId:'',destinationAddress:'',destinationPin:''}]);

let handleChange = e => {
   const {name, value} = e.target;
   const stateClone = state.map((item, i) => ({...state[i], [name]: value }))
   // do what you want to this new array
   setState(stateClone); // update the state array with the new values


}

CodePudding user response:

If you want to update one column of a row, you can create a callback that will take an index (that you'll get when you will render the array of rows) and that will return a callback that will take the event (triggered when the event is dispatched by the browser) and that will update your value.

Then, you only need to trigger a new state change by cloning the old array (using Array.prototype.map) and mapping the new value of the row at any given index. If the index does not match, this means that the row that is mapped is not concerned by the change event so we return the row as-is.

import React, {useState, useCallback} from "react";

const App = () => {
  const [rows, setRows] = useState([
    {id: 1, value: ""},
    {id: 2, value: ""},
    {id: 3, value: ""}
  ]);

  const handleRowValueChange = useCallback(index => ({currentTarget: {value}}) => {
    setRows(rows.map((row, rowIndex) => {
      if (rowIndex === index) {
        return {
          ...row,
          value
        };
      }

      return row;
    }));
  }, [rows]);

  return (
    <table>
      <tbody>
        {rows.map((row, index) => (
          <tr key={row.id}>
            <td>
              <input value={row.value} onChange={handleRowValueChange(index)} />
            </td>
          </tr>
        ))}
      </tbody>
    </table>
  );
};

export default App;

CodePudding user response:

Update your handleChange function definition to

let handleChange = (e)=>{
    let {name,value}=e.target;
    const newData = data.map((ele,id)=>{
        return { ...fvalues[id], [name]: value };
        // setFvalues(fvalues[id].name)
    })
    setFvalues(newData);
    console.log(name,value);
}

Here, you will first create a new array (newData) using data.map and then assign the same as the new state using the setFvalues call.

Currently, you are calling setFvalues inside data.map because of which the state is being updated again and again with an individual array element (an object, in your case) on each iteration of the map method.

  • Related