Reactjs:如何从依赖于子组件状态的父组件中的方法访问子组件的状态 [英] Reactjs: How to access state of child component.from a method in parent component that depends on state of child component
问题描述
我需要访问父组件中定义的方法 handleCancelEdit()
.但是,这里的问题是每个子组件都有自己的 cancelEdit
状态.现在,发生的事情是,如果我从一个子组件调用 handleCancelEdit()
,所有其他相同的子组件都会获取状态并更新自己(该方法尚未完全定义).所以,我在子组件中定义了cancelEdit
状态,认为它只属于这个子组件.
现在,我如何让 handleCancelEdit()
方法对调用它的唯一子组件进行更改?
家长:
function Parent() {const handleCancelEdit = () =>{setCancelEdit(!cancelEdit);//在子组件中定义设置编辑(!编辑);//在子组件中定义...};返回 (<div><子组件fieldName={电子邮件"}值={电子邮件}inputType={文本"}placeHolder={输入电子邮件"}姓名={电子邮件"}on_change={(e)=>setEmail(e.target.value)}on_click={handleUserEmail}/><子组件fieldName={关于"}价值={约}inputType={文本"}placeHolder={请输入有关您自己的一些详细信息"}名称={关于"}on_change={(e)=>setAbout(e.target.value)}on_click={handleUserAbout}/>
);}
子组件:
function ChildComponent({fieldName, value, inputType, placeHolder, name, on_change, on_click}) {const [edit, setEdit] = useState(false);const [cancelEdit, setCancelEdit] = useState(false)const isEdit = 编辑;返回 (<p>{fieldName}: {value === ''?(<跨度><input type={inputType} placeholder={placeHolder}名称={名称} onChange={on_change}/><按钮类型=提交"onClick={on_click}>添加</button></span>) : ( !isEdit ? (<span> {value} <button onClick={e=>setEdit(!edit)}>Edit</button></span>) :(<跨度><输入类型={输入类型}值={值}名称={名称} onChange={on_change}/><按钮类型=提交"onClick={on_click}>保存</button><按钮类型=提交"onClick={handleCancelEdit}>Cancel</button></span>))}</p>);};
我希望它能让一个子组件不应该让其他组件更新是可以理解的.现在,在这种情况下我该怎么做?
编辑
根据 Linda Paiste 进行更改后:
即使父子组件中的 onChange
都正确,子组件中的输入字段不起作用!
向下传递状态和数据总是比向上传递更合乎逻辑.如果 Parent
需要与 edit
状态交互,那么该状态应该存在于父级中.当然,我们希望每个孩子都有独立的 edit
状态,所以父母不能只有一个 boolean
.每个孩子都需要一个 boolean
.我推荐一个由字段的 name
属性键控的 object
.
在ChildComponent
中,我们将isEdit
和setEdit
移动到props.handleCancelEdit
只是 () =>setEdit(false)
(是否也需要清除onChange
设置的状态?)
在Parent
中,我们需要存储那些isEdit
状态,并为每个字段创建一个setEdit
函数.
function Parent() {const [isEditFields, setIsEditFields] = useState({});const handleSetEdit = (name, isEdit) =>{setIsEditFields((prev) => ({...上一个,[名称]:isEdit}));};/* ... */返回 (<div><子组件fieldName={电子邮件"}值={电子邮件}inputType={文本"}placeHolder={输入电子邮件"}姓名={电子邮件"}onChange={(e) =>setEmail(e.target.value)}onSubmit={handleUserEmail}isEdit={isEditFields.email}setEdit={(isEdit) =>handleSetEdit("email", isEdit)}/><子组件fieldName={关于"}价值={约}inputType={文本"}placeHolder={请输入有关您自己的一些详细信息"}名称={关于"}onChange={(e) =>setAbout(e.target.value)}onSubmit={handleUserAbout}isEdit={isEditFields.about}setEdit={(isEdit) =>handleSetEdit("about", isEdit)}/>
);}
您可以通过将 values
存储为单个状态而不是单独的 useState
挂钩来清理大量重复代码.现在可以从 name
自动生成 5 个道具.
function Parent() {const [isEditFields, setIsEditFields] = useState({});const [values, setValues] = useState({关于: '',电子邮件: ''});const getProps = (name) =>({名称,值:值[名称],onChange: (e) =>setValues(prev => ({...上一个,[名称]:e.target.value})),isEdit: isEditFields[name],setEdit: (isEdit) =>setIsEditFields(prev => ({...上一个,[名称]:isEdit}))});const handleUserEmail = console.log//占位符const handleUserAbout = console.log//占位符返回 (<div><子组件fieldName={电子邮件"}inputType={文本"}placeHolder={输入电子邮件"}onSubmit={handleUserEmail}{...getProps("email")}/><子组件fieldName={关于"}inputType={文本"}placeHolder={请输入有关您自己的一些详细信息"}onSubmit={handleUserAbout}{...getProps(关于")}/>
);}
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 happening is, if I call handleCancelEdit()
from one child component, every other of the same child components is taking the state and updating themselves(the method is not completely defined yet). That's why, I have defined the cancelEdit
state in the child component, thinking that it belongs to this child component only.
Now, how do I make the handleCancelEdit()
method make changes to the only child component which called it?
The parent:
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>
);
}
Child component:
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>
);
};
I hope it could make it understandable that one child component should not make others to update. Now, how do I do it in this scenario?
EDIT
After making changes according to Linda Paiste:
The input field in the child component is not working even though the onChange
in both parent and child is correct!
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>
);
}
这篇关于Reactjs:如何从依赖于子组件状态的父组件中的方法访问子组件的状态的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!