Skip to content
Advertisement

React Hooks useState() with an Array of Object

while I am creating new “Todo” and modifying the fields are no problem my issue is receiving back the child data when I click the “show all objects” button.

Here is a code example to illustrate my issue:

const CompoOne = () =>{
  const [todos, setTodos] = useState([])
  const [subject, setSubject] = useState("")
  const [priority, setPriority] = useState("")

  const addTodo = () => setTodos(
     [...todos, { a: "Title", b: "subTitle", c: "content"}]
  )

  return (
        <>
          <InputText
            value={subject}
            setValue={setSubject}
            label="subject field"
          />
          <InputText
            value={priority}
            setValue={setPriority}
            label="priority field"
          />
          <hr />
          <h2>Todo:</h2>
          <hr />
          <button
            onClick={()=>addTodo()}
          >
            add a todo
          </button>
          <>
            {setTodos.map((el,i)=>(
                <CompoTwo
                  todo={el}
                  setTodos={setTodos}
                  todos={todos}
                  key={i}
                />
            )}
          </>

          <button
            onClick={()=>console.log(todos)}
          >
            show all objects
          </button>
        </>
  )
}


const compoTwo = ({ todo, todos, setTodos }) =>{
  const [a, setA] = useState("")
  const [b, setB] = useState("")
  const [c, setC] = useState("")

  const handleChange = (e) =>{
    const {name, value} = e.target
    setTodos((prevState)=>{
      //I would like to update the inside the prevState instance
      const updatedArray = // something like [...prevState, [name]:value]
      // return updatedArray
    })
  }

  return(
    <>
          <InputText
            value={a}
            name="a"
            onChange={(e)=>setA(e.target.value)}
            onBlur={(e) => handleChange(e)}
            label="field A"
          />
          <InputText
            value={b}
            name="b"
            onChange={(e)=>setB(e.target.value)}
            onBlur={(e) => handleChange(e)}
            label="field B"
          />
          <InputText
            value={c}
            name="c"
            onChange={(e)=>setC(e.target.value)}
            onBlur={(e) => handleChange(e)}
            label="field C"
          />
    </>
  )
}

if I click twice on the “add a Todo” button and change one of the field’s values, I will still get the default value

[
  {a: "Title", b: "subTitle", c:"content"},
  {a: "Title", b: "subTitle", c:"content"},
]

and my purpose would be to get the updated value of the child component.

if you got any idea…

here is the code sandbox link to try and play

thanks in advance

Advertisement

Answer

You can try this and hope it may help you for compoTwo.

Note: You can also set the todo prop value as the initial value of useState.

const compoTwo = ({ todo, todos, setTodos }) =>{
  const [a, setA] = useState("")
  const [b, setB] = useState("")
  const [c, setC] = useState("")

  const handleChange = (e) => {
    const { name, value } = e.target;
    setTodos((prevState) => {
      const temp = [...prevState];
      const find = temp.find((res) => res.id === todo.id);
      if (find) {
        find[name] = value;
        return temp;
      } else {
        return prevState;
      }
    });
  };

  return(
    <>
          <InputText
            value={a}
            name="a"
            onChange={(e)=>setA(e.target.value)}
            onBlur={(e) => handleChange(e)}
            label="field A"
          />
          <InputText
            value={b}
            name="b"
            onChange={(e)=>setB(e.target.value)}
            onBlur={(e) => handleChange(e)}
            label="field B"
          />
          <InputText
            value={c}
            name="c"
            onChange={(e)=>setC(e.target.value)}
            onBlur={(e) => handleChange(e)}
            label="field C"
          />
    </>
  )
}

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement