Formik多步骤表单字段验证及动态组件传参问题求助
Hey there! Let's break down how to fix your two key issues with the Formik multi-step form: passing props to dynamically rendered components, and implementing the two-digit input validation with error messages.
1. Passing Props to Dynamically Rendered Components
The problem with your current <div>{pages[state]}</div> approach is that you're directly rendering the component without a way to pass props. Instead, we'll reference the component as a variable and render it with JSX, which lets us pass any props we need (like Formik's errors and touched).
Step 1: Update the SignUp Component
Modify the Formik render block to render the current page component with props:
const SignUp = () => { const currentPageIndex = useSelector((state: RootState) => state); console.log("current page index", currentPageIndex); const dispatch = useDispatch(); // Get the current page component from your pages array const CurrentPage = pages[currentPageIndex]; return ( <Formik initialValues={{ firstName: "", lastName: "", email: "", idealWeight: "" }} // Added idealWeight for semantic clarity onSubmit={values => { setTimeout(() => { alert(JSON.stringify(values, null, 2)); }, 500); }} render={({ errors, touched, isValidating }) => ( <Form> {/* Render the current page with Formik props */} <CurrentPage errors={errors} touched={touched} /> <button type="button" onClick={() => { dispatch(decrement()); }} > Prev </button> <button type="button" onClick={() => { pages.length - 1 <= currentPageIndex ? console.log("No more pages") : dispatch(increment()); }} > Next </button> </Form> )} /> ); };
Step 2: Update Page2 to Receive Props
Now make sure Page2 accepts the props and passes them down to your Input component:
const Page2 = ({ errors, touched }) => { return ( <> <h1> What is your <span id="idealWeightText">ideal weight</span> that you want to reach? </h1> <Input name={"idealWeight"} // Renamed to match initialValues htmlFor={"idealWeight"} type={"number"} validation={validateKilograms} errors={errors} touched={touched} /> </> ); };
2. Implement Two-Digit Validation & Error Messages
Next, we'll create the validation function and update the Input component to display error messages when validation fails.
Step 1: Create the Validation Function
This function checks if the input is a valid two-digit number (10-99):
const validateKilograms = (value) => { let error; if (!value) { error = "Weight is required"; } else { const numValue = Number(value); if (isNaN(numValue) || numValue < 10 || numValue > 99) { error = "Please enter a valid two-digit number (10-99)"; } } return error; };
Step 2: Update the Input Component to Show Errors
Modify the Input component to accept errors and touched, then render the error message when the field has been touched and has an error:
// Extend FieldProps to include errors and touched interface InputProps extends FieldProps { errors?: Record<string, string>; touched?: Record<string, boolean>; } const Input: React.FC<InputProps> = ({ name, onChange, htmlFor, type, validation, placeholder, errors, touched }) => { return ( <div style={{ marginBottom: '16px' }}> <label htmlFor={name}> <Field type={type} name={name} placeholder={placeholder} validate={validation} onChange={onChange} /> kg </label> {/* Show error message only if field is touched and has an error */} {touched?.[name] && errors?.[name] && ( <div style={{ color: '#dc2626', fontSize: '0.875rem', marginTop: '4px' }}> {errors[name]} </div> )} </div> ); };
Key Notes
- I renamed the field from
firstNametoidealWeightin Page2 to make it semantically correct (since it's for weight, not a name). - The validation function checks for empty values, non-numeric inputs, and values outside the 10-99 range.
- Error messages only show after the user has interacted with the field (
touched[name]is true), which is a better UX practice.
内容的提问来源于stack exchange,提问作者Gim-Cojocaru Raul-Cristian

