簡體   English   中英

Reactjs:如何訪問子組件的 state。從依賴於子組件 state 的父組件中的方法

[英]Reactjs: How to access state of child component.from a method in parent component that depends on state of child component

我需要訪問父組件中定義的方法handleCancelEdit() 但是,這里的問題是每個子組件都有自己的cancelEdit state。 現在,正在發生的事情是,如果我從一個子組件調用handleCancelEdit() ,則每個其他相同的子組件都在使用 state 並更新自己(該方法尚未完全定義)。 這就是為什么,我在子組件中定義了cancelEdit state,認為它只屬於這個子組件。

現在,如何使handleCancelEdit()方法更改調用它的唯一子組件?

家長:

function Parent() {
    const handleCancelEdit = () => {
        setCancelEdit(!cancelEdit);  // defined in child component
        setEdit(!edit);       // defined in child component
        ...
    };
    return (
    <div>
        <ChildComponent
            fieldName={"Email"}
            value={email}
            inputType={"text"}
            placeHolder={"Enter email"}
            name={"email"}
            on_change={(e)=>setEmail(e.target.value)}
            on_click={handleUserEmail}
         />
         <ChildComponent
             fieldName={"About"}
             value={about}
             inputType={"text"}
             placeHolder={"Enter some details about yourself"}
             name={"about"}
             on_change={(e)=>setAbout(e.target.value)}
             on_click={handleUserAbout}
         />
    </div>
    );
}

子組件:

function ChildComponent({fieldName, value, inputType, placeHolder, name, on_change, on_click}) {
    const [ edit, setEdit ] = useState(false);
    const [ cancelEdit, setCancelEdit ] = useState(false)
    const isEdit = edit;
    return (
        <p>{fieldName}: {value === ''? (
            <span>
                <input type={inputType} placeholder={placeHolder}
                    name={name}  onChange={on_change}
                />
                <button type="submit" onClick={on_click}>Add</button>
            </span>
            ) : ( !isEdit ? (<span> {value} <button onClick={e=>setEdit(!edit)}>Edit</button></span>) :
            (<span>
                <input type={inputType} value={value}
                        name={name}  onChange={on_change}
                />
                <button type="submit" onClick={on_click}>Save</button>
                <button type="submit" onClick={handleCancelEdit}>Cancel</button>
            </span>)                            
            )}
        </p>
    );
};

我希望它可以理解一個子組件不應該讓其他組件更新。 現在,在這種情況下我該怎么做?

編輯

根據 Linda Paiste 進行更改后: 錯誤的gif

即使父子組件中的onChange正確,子組件中的輸入字段也不起作用!

將 state 和數據向下傳遞而不是向上傳遞總是更合乎邏輯。 如果Parent級需要與edit state 交互,那么 state 應該存在於父級中。 當然,我們希望每個孩子都有獨立的edit狀態,所以父母不能只有一個boolean 每個孩子都需要一個boolean 我推薦一個object由字段的name屬性鍵入。

ChildComponent中,我們將isEditsetEdit移動到 props。 handleCancelEdit只是() => setEdit(false) (是否還需要清除onChange設置的 state ?)。


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>
    );
};

Parent中,我們需要存儲這些isEdit狀態,並為每個字段創建一個setEdit function。

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>
  );
}

您可以通過將values存儲為單個 state 而不是單個useState掛鈎來清理大量重復的代碼。 現在 5 個 props 可以僅從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>
  );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM