Napisałem 3 stopniowy formularz w react-final-form. Przy próbie dodania walidacji, wyrzuca mi błąd :
Property 'validate' does not exist on type 'string | number | {} | ReactElement<any, string | ((props: any) => ReactElement<any, string | ... | (new (props: any) => Component<any, any, any>)> | null) | (new (props: any) => Component<...>)> | ReactNodeArray | ReactPortal'.
Property 'validate' does not exist on type 'string'.ts(2339)
Dopiero zaczynam się uczyć TypeScript i nie mogę dojść, gdzie jest błąd w kodzie. Formularz jest podzielony na 3 części - WizardPage (komponent funkcyjny wyświetlający children), dla którego stworzyłem typ, ponieważ w momencie tworzenia przekazuje w propsach funkcję validate, która sprawdza mi podane dane. Błąd wyrzuca przy próbie połączenia tego z głównym formularzem ( linia 52-53 ) i nie potrafię dojść o co chodzi...
wizard.tsx
import React, { useState } from "react";
import { Form } from "react-final-form";
import styles from "./register.module.scss";
import { Values } from "./register";
type Wizard = {
onSubmit: (values: Values) => void;
};
type WizardPage = {
validate: (
values: Values
) => {
error1: String;
error2: String;
error3?: String;
error4?: String;
};
};
export const WizardPage: React.FC<WizardPage> = ({ validate, children }) => (
<div className={styles.wizard}>{children}</div>
);
// 3-steps form
const Wizard: React.FC<Wizard> = ({ onSubmit, children }) => {
const [page, setPage] = useState(0);
const [values, setValues] = useState<Values | undefined>(undefined);
const activePage = React.Children.toArray(children)[page];
const isLastPage = page === React.Children.count(children) - 1;
// next page
const next = (values: Values) => {
setPage(Math.min(page + 1, React.Children.count(children)));
setValues(values);
};
// previous page
const previous = () => {
setPage(Math.max(page - 1, 0));
};
const handleSubmit = (values: Values) => {
const isLastPage = page === React.Children.count(children) - 1;
if (isLastPage) {
return onSubmit(values);
} else {
next(values);
}
};
const validate = (values: Values) => {
return activePage.validate(values);
};
return (
<Form onSubmit={handleSubmit} validate={validate}>
{({ handleSubmit, submitting, values }) => {
return (
<form className={styles.moblieForm} onSubmit={handleSubmit}>
{activePage}
<div
className={styles.buttons}
style={page === 0 ? { justifyContent: "flex-end" } : {}}
>
{page > 0 && (
<button type="button" onClick={previous}>
Powrót
</button>
)}
{!isLastPage && <button type="submit">Dalej</button>}
{isLastPage && (
<button type="submit" disabled={submitting}>
Zakończ
</button>
)}
</div>
</form>
);
}}
</Form>
);
};
export default Wizard;
register.tsx
import React from "react";
import { Field } from "react-final-form";
import Wizard, { WizardPage } from "./wizard";
import TextInput from "../../../../components/form/textInput";
import styles from "./register.module.scss";
export type Values = {
name: String;
surname: String;
email: String;
password: String;
city: String;
birthDay: Number;
birthMonth: Number;
birthYear: Number;
};
const Register: React.FC = () => {
const onSubmit = (values: Values) => {
console.log(values);
};
return (
<Wizard onSubmit={onSubmit}>
<WizardPage
validate={(values: Values) => {
const errors = {
error1: "",
error2: "",
};
if (!values.name) {
errors.error1 = "Required";
}
if (!values.surname) {
errors.error2 = "Required";
}
return errors;
}}
>
<Field<string>
type="text"
name="name"
component={TextInput}
placeholder="Imię"
/>
<Field<string>
type="text"
name="surname"
component={TextInput}
placeholder="Nazwisko"
/>
</WizardPage>
<WizardPage
validate={(values: Values) => {
const errors = {
error1: "",
error2: "",
};
if (!values.email) {
errors.error1 = "Required";
}
if (!values.password) {
errors.error2 = "Required";
}
return errors;
}}
>
<Field<string>
type="email"
name="email"
component={TextInput}
placeholder="E-mail"
/>
<Field<string>
type="password"
name="password"
component={TextInput}
placeholder="Hasło"
/>
</WizardPage>
<WizardPage
validate={(values: Values) => {
const errors = {
error1: "",
error2: "",
error3: "",
error4: "",
};
if (!values.city) {
errors.error1 = "Required";
}
if (!values.birthDay) {
errors.error2 = "Required";
}
if (!values.birthMonth) {
errors.error3 = "Required";
}
if (!values.birthYear) {
errors.error4 = "Required";
}
return errors;
}}
>
<Field<string>
type="text"
name="city"
component={TextInput}
placeholder="Miasto"
/>
<label>Data urodzenia:</label>
<div className={styles.birthdayInputs}>
<Field<string>
type="text"
name="birthDay"
component={TextInput}
placeholder="Dzień"
style={{ marginRight: "1rem" }}
/>
<Field<string>
type="text"
name="birthMonth"
component={TextInput}
placeholder="Miesiąc"
style={{ marginRight: "1rem" }}
/>
<Field<string>
type="text"
name="birthYear"
component={TextInput}
placeholder="Rok"
/>
</div>
</WizardPage>
</Wizard>
);
};
export default Register;