在反应中提交表单数据
Submit forms data in react
我有一些组件,在每个组件中,我都有一个表单,单击下一个我打开一个新表单(调用新组件),当它是最后一个时,我将其更改为提交。
我想达到的目标
1:在每次单击和返回时,我想使用 react-form-hook 验证我的表单
2:点击提交我应该可以看到所有数据
3: 当点击后面的数据不应该从输入中丢失
问题
所以我使用 react-hook-form 进行验证,因为它使用起来非常简单,但是在这里我无法找到,因为我的按钮不在它们位于主要组件中的表单中,所以我将如何验证并提交表单,然后点击提交所有数据。
我的代码
import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";
function AddCompanyMain() {
const [currState, setCurrState] = useState(1);
const [allState, setAllstate] = useState(3);
const moveToPrevious = () => {
setCurrState(currState - 1);
};
const moveToNext = () => {
setCurrState(currState + 1);
};
return (
<div>
<div class="progress">
<div>{currState}</div>
</div>
{currState === 1 && <Form1 />}
{currState === 2 && <Form2 />}
{currState === 3 && <Form3 />}
{currState !== 1 && (
<button
className="btn btn-primary"
type="button"
onClick={moveToPrevious}
>
back
</button>
)}
{currState !== allState && (
<button className="btn btn-primary" type="button" onClick={moveToNext}>
next
</button>
)}
{currState === 3 && (
<button className="btn btn-primary" type="submit">
Submit
</button>
)}
</div>
);
}
export default AddCompanyMain;
我的完整代码Code sandbox
我只是在寻找一个好的方法,因为这里我不能在每个组件中提交,因为我必须在顶部显示步骤。
您可以 lift the value state of each component up to the parent,然后将 onChange 属性传递给每个子对象以更新每个子对象的状态。我不确定这将如何与 react-hooks-form 一起玩,但这通常是您希望同步子组件状态的方式。
import React from "react";
import "./styles.css";
const FormOne = ({ value, onChange }) => (
<div>
Form 1
<input type='text' value={value} onChange={e => onChange(e.target.value)} />
</div>
)
const FormTwo = ({ value, onChange }) => (
<div>
Form 2
<input type='text' value={value} onChange={e => onChange(e.target.value)} />
</div>
)
const FormThree = ({ value, onChange }) => (
<div>
Form 3
<input type='text' value={value} onChange={e => onChange(e.target.value)} />
</div>
)
export default function App() {
const [formOne, setFormOne] = React.useState('')
const [formTwo, setFormTwo] = React.useState('')
const [formThree, setFormThree] = React.useState('')
const [index, setIndex] = React.useState(0)
const moveUp = (e) => {
e.preventDefault()
if (index !== 2) {
setIndex(index => index += 1)
}
}
const moveDown = (e) => {
e.preventDefault()
if (index !== 0) {
setIndex(index => index -= 1)
}
}
const handleSubmit = (e) => {
e.preventDefault()
console.log(formOne, formTwo, formThree)
}
const form = index === 0
? <FormOne value={formOne} onChange={setFormOne} />
: index === 1
? <FormTwo value={formTwo} onChange={setFormTwo} />
: <FormThree value={formThree} onChange={setFormThree} />
return (
<div className="App">
<form onSubmit={handleSubmit}>
{form}
{index !== 0 && <button onClick={moveDown}>Back</button>}
{index !== 2
? <button onClick={moveUp}>Next</button>
: <button type='submit'>Submit</button>
}
</form>
</div>
);
}
您可以通过以下方式解决您的问题:
- 在app.js中,将表单存储在一个对象数组中,并根据步骤(当前状态)呈现它们。
- 在父组件(而不是子表单组件)中调用
useForm
并将 register, errors, defaultValues
值作为 props 传递给您的 Form
组件。
- 在你的
Form
组件中,你需要获取 register, etc
作为 props
- 保持
defaultValues
状态,并在next/previous的onClick
中更新它们。您需要 getValues and then use setValues 来设置状态(默认值)
另外:
为了在 next/previous 按钮点击时触发验证,您需要使用 triggerValidation
为了在点击next/previous时保留值,需要使用defaultValuesprop
代码段
import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";
import { useForm } from "react-hook-form";
function AddCompanyMain() {
const {
register,
triggerValidation,
errors,
setValue,
getValues
} = useForm();
const [defaultValues, setDefaultValues] = useState({});
const forms = [
{
fields: ["uname"],
component: (register, errors, defaultValues) => (
<Form1
register={register}
errors={errors}
defaultValues={defaultValues}
/>
)
},
{
fields: ["lname"],
component: (register, errors, defaultValues) => (
<Form2
register={register}
errors={errors}
defaultValues={defaultValues}
/>
)
},
{
fields: ["company"],
component: (register, errors, defaultValues) => (
<Form3
register={register}
errors={errors}
defaultValues={defaultValues}
/>
)
}
];
const [currentForm, setCurrentForm] = useState(0);
const moveToPrevious = () => {
setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));
triggerValidation(forms[currentForm].fields).then(valid => {
if (valid) setCurrentForm(currentForm - 1);
});
};
const moveToNext = () => {
console.log(getValues());
setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));
triggerValidation(forms[currentForm].fields).then(valid => {
if (valid) setCurrentForm(currentForm + 1);
});
};
const prevButton = currentForm !== 0;
const nextButton = currentForm !== forms.length - 1;
return (
<div>
<div class="progress">
<div>{currentForm}</div>
</div>
{forms[currentForm].component(
register,
errors,
defaultValues[currentForm]
)}
{prevButton && (
<button
className="btn btn-primary"
type="button"
onClick={moveToPrevious}
>
back
</button>
)}
{nextButton && (
<button className="btn btn-primary" type="button" onClick={moveToNext}>
next
</button>
)}
{currentForm === 3 && (
<button className="btn btn-primary" type="submit">
Submit
</button>
)}
</div>
);
}
export default AddCompanyMain;
注意 - 通常,在使用多步骤表单时,最好使用受控组件并在父组件中维护状态
我有一些组件,在每个组件中,我都有一个表单,单击下一个我打开一个新表单(调用新组件),当它是最后一个时,我将其更改为提交。
我想达到的目标
1:在每次单击和返回时,我想使用 react-form-hook 验证我的表单
2:点击提交我应该可以看到所有数据
3: 当点击后面的数据不应该从输入中丢失
问题
所以我使用 react-hook-form 进行验证,因为它使用起来非常简单,但是在这里我无法找到,因为我的按钮不在它们位于主要组件中的表单中,所以我将如何验证并提交表单,然后点击提交所有数据。
我的代码
import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";
function AddCompanyMain() {
const [currState, setCurrState] = useState(1);
const [allState, setAllstate] = useState(3);
const moveToPrevious = () => {
setCurrState(currState - 1);
};
const moveToNext = () => {
setCurrState(currState + 1);
};
return (
<div>
<div class="progress">
<div>{currState}</div>
</div>
{currState === 1 && <Form1 />}
{currState === 2 && <Form2 />}
{currState === 3 && <Form3 />}
{currState !== 1 && (
<button
className="btn btn-primary"
type="button"
onClick={moveToPrevious}
>
back
</button>
)}
{currState !== allState && (
<button className="btn btn-primary" type="button" onClick={moveToNext}>
next
</button>
)}
{currState === 3 && (
<button className="btn btn-primary" type="submit">
Submit
</button>
)}
</div>
);
}
export default AddCompanyMain;
我的完整代码Code sandbox
我只是在寻找一个好的方法,因为这里我不能在每个组件中提交,因为我必须在顶部显示步骤。
您可以 lift the value state of each component up to the parent,然后将 onChange 属性传递给每个子对象以更新每个子对象的状态。我不确定这将如何与 react-hooks-form 一起玩,但这通常是您希望同步子组件状态的方式。
import React from "react";
import "./styles.css";
const FormOne = ({ value, onChange }) => (
<div>
Form 1
<input type='text' value={value} onChange={e => onChange(e.target.value)} />
</div>
)
const FormTwo = ({ value, onChange }) => (
<div>
Form 2
<input type='text' value={value} onChange={e => onChange(e.target.value)} />
</div>
)
const FormThree = ({ value, onChange }) => (
<div>
Form 3
<input type='text' value={value} onChange={e => onChange(e.target.value)} />
</div>
)
export default function App() {
const [formOne, setFormOne] = React.useState('')
const [formTwo, setFormTwo] = React.useState('')
const [formThree, setFormThree] = React.useState('')
const [index, setIndex] = React.useState(0)
const moveUp = (e) => {
e.preventDefault()
if (index !== 2) {
setIndex(index => index += 1)
}
}
const moveDown = (e) => {
e.preventDefault()
if (index !== 0) {
setIndex(index => index -= 1)
}
}
const handleSubmit = (e) => {
e.preventDefault()
console.log(formOne, formTwo, formThree)
}
const form = index === 0
? <FormOne value={formOne} onChange={setFormOne} />
: index === 1
? <FormTwo value={formTwo} onChange={setFormTwo} />
: <FormThree value={formThree} onChange={setFormThree} />
return (
<div className="App">
<form onSubmit={handleSubmit}>
{form}
{index !== 0 && <button onClick={moveDown}>Back</button>}
{index !== 2
? <button onClick={moveUp}>Next</button>
: <button type='submit'>Submit</button>
}
</form>
</div>
);
}
您可以通过以下方式解决您的问题:
- 在app.js中,将表单存储在一个对象数组中,并根据步骤(当前状态)呈现它们。
- 在父组件(而不是子表单组件)中调用
useForm
并将register, errors, defaultValues
值作为 props 传递给您的Form
组件。 - 在你的
Form
组件中,你需要获取register, etc
作为 props - 保持
defaultValues
状态,并在next/previous的onClick
中更新它们。您需要 getValues and then use setValues 来设置状态(默认值)
另外:
为了在 next/previous 按钮点击时触发验证,您需要使用 triggerValidation
为了在点击next/previous时保留值,需要使用defaultValuesprop
代码段
import React, { useState } from "react";
import Form1 from "./components/Form1";
import Form2 from "./components/Form2";
import Form3 from "./components/Form3";
import { useForm } from "react-hook-form";
function AddCompanyMain() {
const {
register,
triggerValidation,
errors,
setValue,
getValues
} = useForm();
const [defaultValues, setDefaultValues] = useState({});
const forms = [
{
fields: ["uname"],
component: (register, errors, defaultValues) => (
<Form1
register={register}
errors={errors}
defaultValues={defaultValues}
/>
)
},
{
fields: ["lname"],
component: (register, errors, defaultValues) => (
<Form2
register={register}
errors={errors}
defaultValues={defaultValues}
/>
)
},
{
fields: ["company"],
component: (register, errors, defaultValues) => (
<Form3
register={register}
errors={errors}
defaultValues={defaultValues}
/>
)
}
];
const [currentForm, setCurrentForm] = useState(0);
const moveToPrevious = () => {
setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));
triggerValidation(forms[currentForm].fields).then(valid => {
if (valid) setCurrentForm(currentForm - 1);
});
};
const moveToNext = () => {
console.log(getValues());
setDefaultValues(prev => ({ ...prev, [currentForm]: getValues() }));
triggerValidation(forms[currentForm].fields).then(valid => {
if (valid) setCurrentForm(currentForm + 1);
});
};
const prevButton = currentForm !== 0;
const nextButton = currentForm !== forms.length - 1;
return (
<div>
<div class="progress">
<div>{currentForm}</div>
</div>
{forms[currentForm].component(
register,
errors,
defaultValues[currentForm]
)}
{prevButton && (
<button
className="btn btn-primary"
type="button"
onClick={moveToPrevious}
>
back
</button>
)}
{nextButton && (
<button className="btn btn-primary" type="button" onClick={moveToNext}>
next
</button>
)}
{currentForm === 3 && (
<button className="btn btn-primary" type="submit">
Submit
</button>
)}
</div>
);
}
export default AddCompanyMain;
注意 - 通常,在使用多步骤表单时,最好使用受控组件并在父组件中维护状态