Skip to content Skip to sidebar Skip to footer

Reactjs: How To Access State Of Child Component.from A Method In Parent Component That Depends On State Of Child Component

I need to access a method handleCancelEdit() defined in parent component. But, the matter here is that every child component will have its own cancelEdit state. Now, what is happen

Solution 1:

It is always more logical to pass state and data down rather than up. If the Parent needs to interact with the edit state then that state should live in the parent. Of course we want independent edit states for each child, so the parent can't just have one boolean. It needs a boolean for each child. I recommend an object keyed by the name property of the field.

In ChildComponent, we move isEdit and setEdit to props. handleCancelEdit is just () => setEdit(false) (does it also need to clear the state set by onChange?).


function ChildComponent({fieldName, value, inputType, placeHolder, name, onChange, onSubmit, isEdit, setEdit}) {
    return (
        <p>{fieldName}: {value === ''? (
            <span>
                <input type={inputType} placeholder={placeHolder}
                    name={name}  onChange={onChange}
                />
                <button type="submit" onClick={onSubmit}>Add</button>
            </span>
            ) : ( !isEdit ? (<span> {value} <button onClick={() =>setEdit(true)}>Edit</button></span>) :
            (<span>
                <input type={inputType} value={value}
                        name={name}  onChange={onChange}
                />
                <button type="submit" onClick={onSubmit}>Save</button>
                <button type="submit" onClick={() => setEdit(false)}>Cancel</button>
            </span>)                            
            )}
        </p>
    );
};

In Parent, we need to store those isEdit states and also create a setEdit function for each field.

function Parent() {
  const [isEditFields, setIsEditFields] = useState({});

  const handleSetEdit = (name, isEdit) => {
    setIsEditFields((prev) => ({
      ...prev,
      [name]: isEdit
    }));
  };

  /* ... */

  return (
    <div>
      <ChildComponent
        fieldName={"Email"}
        value={email}
        inputType={"text"}
        placeHolder={"Enter email"}
        name={"email"}
        onChange={(e) => setEmail(e.target.value)}
        onSubmit={handleUserEmail}
        isEdit={isEditFields.email}
        setEdit={(isEdit) => handleSetEdit("email", isEdit)}
      />
      <ChildComponent
        fieldName={"About"}
        value={about}
        inputType={"text"}
        placeHolder={"Enter some details about yourself"}
        name={"about"}
        onChange={(e) => setAbout(e.target.value)}
        onSubmit={handleUserAbout}
        isEdit={isEditFields.about}
        setEdit={(isEdit) => handleSetEdit("about", isEdit)}
      />
    </div>
  );
}

You can clean up a lot of repeated code by storing the values as a single state rather than individual useState hooks. Now 5 of the props can be generated automatically just from the name.

function Parent() {
  const [isEditFields, setIsEditFields] = useState({});

  const [values, setValues] = useState({
      about: '',
      email: ''
  });

  const getProps = (name) => ({
      name,
      value: values[name],
      onChange: (e) => setValues(prev => ({
          ...prev,
          [name]: e.target.value
      })),
      isEdit: isEditFields[name],
      setEdit: (isEdit) => setIsEditFields(prev => ({
          ...prev,
          [name]: isEdit
      }))
  });

  const handleUserEmail = console.log // placeholder
  const handleUserAbout = console.log // placeholder

  return (
    <div>
      <ChildComponent
        fieldName={"Email"}
        inputType={"text"}
        placeHolder={"Enter email"}
        onSubmit={handleUserEmail}
        {...getProps("email")}
      />
      <ChildComponent
        fieldName={"About"}
        inputType={"text"}
        placeHolder={"Enter some details about yourself"}
        onSubmit={handleUserAbout}
        {...getProps("about")}
      />
    </div>
  );
}

Post a Comment for "Reactjs: How To Access State Of Child Component.from A Method In Parent Component That Depends On State Of Child Component"