Home > Back-end >  Storing state of child components with clean code
Storing state of child components with clean code

Time:11-17

Short Explanation I just want to get the data from the textboxes and send them to the server. In jquery I would just list out all my textboxes and get the value and form the json and send it to the server

Please see example code https://codesandbox.io/s/xenodochial-euclid-3bl7tc

const EMPTY_VALUE = "";
const App = () => {
  const [valueFirstName, setValueFirstName] = React.useState(EMPTY_VALUE);
  const [valueMiddleName, setValueMiddleName] = React.useState(EMPTY_VALUE);
  const [valueLastName, setValueLastName] = React.useState(EMPTY_VALUE);

  return (
    <div>
      First Name:
      <Work365TextBox value={valueFirstName} setValue={setValueFirstName} />
      <div>{valueFirstName}</div>
      Middle Name:
      <Work365TextBox value={valueMiddleName} setValue={setValueMiddleName} />
      <div>{valueMiddleName}</div>
      Last Name:
      <Work365TextBox value={valueLastName} setValue={setValueLastName} />
      <div>{valueLastName}</div>
    </div>
  );
};

Problem

The current code has a label for first name, middle name, and last name and components to contain the textboxes and then the state of the component is stored in the parent.Then the parent takes the state and displays it below the textbox. So the solution works great. But the code is messy

Question If I have a form that asks for 20 values what is a cleaner way to handle this ? I have tried to do this with by defining a object as json and calling a method when the value in each textbox changes but then I need to have a method for each textbox I have on the screen and it doesn't seem very clean. How would you solve this problem in a clean way ? Preferably I want to be able to have 50 textbox components but just call one method to update state.

CodePudding user response:

the object solution you mentioned is a great way. one thing to add is that you can pass a name prop to your input and then in the onChange method you can access it via event.target.name that way you can dynamically update your object something like this

  const onChangeHandler = (event) => {
    const name = event.target.name;
    const value = event.target.value;
    setState((prev) => ({ ...prev, [name]: value }));
  };

another solution is to define it with useReducer but that will need a extra code.

CodePudding user response:

I would just use an array like that:

// one item for each textbox
const textboxes = [
  {
    // human-readable label
    label: "First name",
    // unique key for data access
    key: "firstName"
  },
  {
    label: "Middle name",
    key: "middleName"
  },
  {
    label: "Last name",
    key: "lastName"
  }
];

A state like this:

const [values, setValues] = React.useState(
  // converts array to record-like object
  Object.fromEntries(textboxes.map((box) => [box.key, ""]))
);

const handleChange = (key, value) => {
  setValues((values) => ({ ...values, [key]: value }));
};

And render it like this:

<div>
  {textboxes.map((box) => (
    <>
      {box.label}:
      <Work365TextBox
        value={values[box.key]}
        setValue={(value) => handleChange(box.key, value)}
      />
      <div>{values[box.key]}</div>
    </>
  ))}
</div>

Full example

  • Related