Reactjs React从父组件收集有关某个事件的子组件数据
在react最佳实践中,数据流从父级流向子级,事件将从子级传递到父级 在这个UI中,我们有一个父组件,它包含两个子组件和表单。现在,当用户单击父组件中的submit按钮时,我们必须从子组件收集数据 可能的解决方案(不良解决方案|反模式):Reactjs React从父组件收集有关某个事件的子组件数据,reactjs,Reactjs,在react最佳实践中,数据流从父级流向子级,事件将从子级传递到父级 在这个UI中,我们有一个父组件,它包含两个子组件和表单。现在,当用户单击父组件中的submit按钮时,我们必须从子组件收集数据 可能的解决方案(不良解决方案|反模式): 从子级传递ref并从父级触发子方法以收集数据(从父级访问子方法不是一个好主意) onFormData(数据){ //这里收集孩子的数据 } onSubmit(){ //在子对象中触发数据的方法 aRef.collectData() } 提交 将道具绑定到
onFormData(数据){
//这里收集孩子的数据
}
onSubmit(){
//在子对象中触发数据的方法
aRef.collectData()
}
提交
onFormData(数据){
//这里收集孩子的数据
}
onSubmit(){
//更新randomValue,该值将在从子级调用onData方法的useEffect中观察到
randomValue=Math.random();
}
提交
有没有其他处理这些场景的最佳方法?如何避免此UI出现反模式?我通常做的是将状态提升到父级。这意味着我不会打破自然的反应流程,也就是从父母向孩子传递道具。按照您的示例,我会将所有逻辑放在父级中(提交函数、表单状态等)
Const Parent=()=>{
const[formData,setFormData]=useState({})
const onSubmitForm=()=>{
//将表单数据发送到某处
}
返回(
onSubmitForm()}>my按钮
)
}
现在,每当ChildrenForm中的输入发生更改时,我都会在ChildrenForm中使用onChange
函数来更新formData
。因此,我的所有状态都将在父级,我不需要担心必须放弃一切,从子级到父级(如您所述的反模式)我通常做的是将状态提升到父级。这意味着我不会打破自然的反应流程,也就是从父母向孩子传递道具。按照您的示例,我会将所有逻辑放在父级中(提交函数、表单状态等)
Const Parent=()=>{
const[formData,setFormData]=useState({})
const onSubmitForm=()=>{
//将表单数据发送到某处
}
返回(
onSubmitForm()}>my按钮
)
}
现在,每当ChildrenForm中的输入发生更改时,我都会在ChildrenForm中使用onChange
函数来更新formData
。因此,我的所有状态都将在父级,我不需要担心从子级到父级(如您所述的反模式)有第三种选择(这是标准方式):您不收集数据,而是将您的formData
和setFormData
作为道具传递给每个子级。使用方法
每个Child
用formData
填充其输入值,并使用setFormData
更新位于Parent
上的formData
。最后,在提交时,您只需为请求调用设置formData
下面是一个例子:
const ChildA = ({ formData, setFormData }) => {
const { name, age } = formData
const onChange = ({ target: { name, value } }) => { // destructuring 'name' and 'value'
setFormData(formData => ({ ...formData, [name]: value })) // spread formData, update field with 'name' key
}
return (
<>
<label>Name<input type="text" onChange={onChange} name="name" value={name} /></label>
<label>Age<input type="number" onChange={onChange} name="age" value={age} /></label>
</>
);
}
const ChildB = ({ formData, setFormData }) => {
const { email, acceptTerms } = formData
const onChange = ({ target: { name, value } }) => {
setFormData(formData => ({ ...formData, [name]: value }))
}
const onClick = ({ target: { name, checked } }) => {
setFormData(formData => ({ ...formData, [name]: checked }))
}
return (
<>
<label>email<input type="email" onChange={onChange} name="email" value={email} /></label>
<label>Accept Terms<input type="checkbox" onChange={onClick} name="acceptTerms" checked={acceptTerms} /></label>
</>
);
}
const Parent = () => {
// used one formData. you could break down into more if you prefer
const [formData, setFormData] = useState({ name: '', age: null, acceptTerms: false, email: undefined })
const onSubmit = (e) => {
e.preventDefault()
// here you implement logic to submit form
console.log(formData)
}
return (
<>
<ChildA formData={formData} setFormData={setFormData} />
<ChildB formData={formData} setFormData={setFormData} />
<button type="submit" onClick={onSubmit}>Submit</button>
</>
);
}
const ChildA=({formData,setFormData})=>{
常量{name,age}=formData
const onChange=({target:{name,value}}})=>{//对“name”和“value”进行解构
setFormData(formData=>({…formData,[名称]:值}))//扩展formData,使用'name'键更新字段
}
返回(
名称
年龄
);
}
const ChildB=({formData,setFormData})=>{
const{email,acceptTerms}=formData
const onChange=({target:{name,value}})=>{
setFormData(formData=>({…formData,[名称]:值}))
}
const onClick=({target:{name,checked}})=>{
setFormData(formData=>({…formData,[名称]:选中}))
}
返回(
电子邮件
接受条件
);
}
常量父项=()=>{
//使用了一个formData。如果愿意,可以细分为更多
const[formData,setFormData]=useState({name:'',年龄:null,acceptTerms:false,电子邮件:undefined})
const onSubmit=(e)=>{
e、 预防默认值()
//在这里,您实现了提交表单的逻辑
console.log(formData)
}
返回(
提交
);
}
还有第三种选择(这是标准方法):您不收集数据,而是将formData
和setFormData
作为道具传递给每个子项。使用方法
每个Child
用formData
填充其输入值,并使用setFormData
更新位于Parent
上的formData
。最后,在提交时,您只需为请求调用设置formData
下面是一个例子:
const ChildA = ({ formData, setFormData }) => {
const { name, age } = formData
const onChange = ({ target: { name, value } }) => { // destructuring 'name' and 'value'
setFormData(formData => ({ ...formData, [name]: value })) // spread formData, update field with 'name' key
}
return (
<>
<label>Name<input type="text" onChange={onChange} name="name" value={name} /></label>
<label>Age<input type="number" onChange={onChange} name="age" value={age} /></label>
</>
);
}
const ChildB = ({ formData, setFormData }) => {
const { email, acceptTerms } = formData
const onChange = ({ target: { name, value } }) => {
setFormData(formData => ({ ...formData, [name]: value }))
}
const onClick = ({ target: { name, checked } }) => {
setFormData(formData => ({ ...formData, [name]: checked }))
}
return (
<>
<label>email<input type="email" onChange={onChange} name="email" value={email} /></label>
<label>Accept Terms<input type="checkbox" onChange={onClick} name="acceptTerms" checked={acceptTerms} /></label>
</>
);
}
const Parent = () => {
// used one formData. you could break down into more if you prefer
const [formData, setFormData] = useState({ name: '', age: null, acceptTerms: false, email: undefined })
const onSubmit = (e) => {
e.preventDefault()
// here you implement logic to submit form
console.log(formData)
}
return (
<>
<ChildA formData={formData} setFormData={setFormData} />
<ChildB formData={formData} setFormData={setFormData} />
<button type="submit" onClick={onSubmit}>Submit</button>
</>
);
}
const ChildA=({formData,setFormData})=>{
常量{name,age}=formData
const onChange=({target:{name,value}}})=>{//对“name”和“value”进行解构
setFormData(formData=>({…formData,[名称]:值}))//扩展formData,使用'name'键更新字段
}
返回(
名称
年龄
);
}
const ChildB=({formData,setFormData})=>{
const{email,acceptTerms}=formData
const onChange=({target:{name,value}})=>{
setFormData(formData=>({…formData,[名称]:值}))
}
const onClick=({target:{name,checked}})=>{
setFormData(formData=>({…formData,[名称]:选中}))
}
返回(
电子邮件
接受条件
);
}
常量父项=()=>{
//使用了一个formData。如果愿意,可以细分为更多
const[formData,setFormData]=useState({name:'',年龄:null,acceptTerms:false,电子邮件:undefined})
const onSubmit=(e)=>{
e、 上
Const Parent = () => {
const [formData, setFormData] = useState({})
const onSubmitForm = () => {
// send formData to somewhere
}
return (
<ChildrenForm onChange={setFormData} formData={formData} />
<button onSubmit={() => onSubmitForm()}>my button</button>
)
}
const ChildA = ({ formData, setFormData }) => {
const { name, age } = formData
const onChange = ({ target: { name, value } }) => { // destructuring 'name' and 'value'
setFormData(formData => ({ ...formData, [name]: value })) // spread formData, update field with 'name' key
}
return (
<>
<label>Name<input type="text" onChange={onChange} name="name" value={name} /></label>
<label>Age<input type="number" onChange={onChange} name="age" value={age} /></label>
</>
);
}
const ChildB = ({ formData, setFormData }) => {
const { email, acceptTerms } = formData
const onChange = ({ target: { name, value } }) => {
setFormData(formData => ({ ...formData, [name]: value }))
}
const onClick = ({ target: { name, checked } }) => {
setFormData(formData => ({ ...formData, [name]: checked }))
}
return (
<>
<label>email<input type="email" onChange={onChange} name="email" value={email} /></label>
<label>Accept Terms<input type="checkbox" onChange={onClick} name="acceptTerms" checked={acceptTerms} /></label>
</>
);
}
const Parent = () => {
// used one formData. you could break down into more if you prefer
const [formData, setFormData] = useState({ name: '', age: null, acceptTerms: false, email: undefined })
const onSubmit = (e) => {
e.preventDefault()
// here you implement logic to submit form
console.log(formData)
}
return (
<>
<ChildA formData={formData} setFormData={setFormData} />
<ChildB formData={formData} setFormData={setFormData} />
<button type="submit" onClick={onSubmit}>Submit</button>
</>
);
}
// Parent component
let [randomValue, setRandomValue] = React.useState(Math.random());
const onSubmit = () => {
setRandomValue(Math.random());
console.log("click");
}
const onFormData = data => {
console.log(`${data}`);
}
...
<Child triggerSubmit={randomValue} onData={onFormData}/>
// Child component
useEffect(() => {
console.log("child id here");
prop.onData(`Hey Ho! Lets go!`)
}, [prop.triggerSubmit]);