简体   繁体   中英

How to update the state based on my initial state

What I'm trying to do here is to build a dynamic component, that will be responsible to take an array of objects and the form will be built based on my formState. So I made my initial State and used.map to make the loop over the state and mapped the keys to making the label, value, and inputs appear based on the state. but my problem is at onChange. How to update the value key in every object and set the new state for it. any advice, please.

import { useState } from "react";
import InputText from "./components";
import useForm from "./hooks/useForm";

function App() {
  interface formStateT {
    id: number;
    label: string;
    value: any;
    error: string;
  }

  const formState = [
    {
      id: 0,
      label: "firstName",
      value: "",
      error: "",
    },
    {
      id: 1,
      label: "lastName",
      value: "",
      error: "",
    },
  ];

  const { form, validate, setForm, checkValidHandler } = useForm(formState);
  const [error, setError] = useState("");

  const submitFormHandler = (e: { preventDefault: () => void }) => {
    e.preventDefault();

    checkValidHandler();

    // write form logic
    // setError() will be used to take the error message

    console.log(form);
  };

  return (
    <form onSubmit={(e) => submitFormHandler(e)}>
      {form.map((f: formStateT) => (
        <InputText
          key={f.id}
          label={f.label}
          value={f.value}
          onChange={(e) => {
            // Im trying here to update the value key of every label key.
            // setForm({ ...form, [f.label.valueOf()]: f.value })
          }}
          valid={f.value === "" ? validate.notValid : validate.valid}
          errorMsg={error === "" ? f.error : error}
          classes={"class"}
        />
      ))}
      <button>Submit</button>
    </form>
  );
}

export default App;

From your comment, f.value = e.target.value; is a state mutation and should be avoided, the setForm([...form]); is masking the mutation.

In App create an onChangeHandler function that takes the onChange event object and the index you want to update. Unpack the value from the onChange event and update the state. The handler should use a functional state update to update from the previous state, and create a shallow copy of the form array, using the index to shallow copy and update the correct array element.

Example:

// curried function to close over index in scope, and
// return handler function to consume event object
const onChangeHandler = index => e => {
  const { value } = e.target;
  setForm(form => form.map((el, i) => 
    i === index
      ? { ...el, value }
      : el
  ));
};

...

<form onSubmit={submitFormHandler}>
  {form.map((f: formStateT, index: number) => (
    <InputText
      key={f.id}
      label={f.label}
      value={f.value}
      onChange={onChangeHandler(index)} // <-- invoke and pass mapped index
      valid={f.value === "" ? validate.notValid : validate.valid}
      errorMsg={error === "" ? f.error : error}
      classes={"class"}
    />
  ))}
  <button>Submit</button>
</form>

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