TypeScript+React项目中withFormik HOC如何将API返回值设为initialValue
解决方案
方案1:直接在组件内调用Formik实例方法回填(适配你现有代码结构,改动最小)
你已经开启了enableReinitialize配置,且Login组件接收的FormikProps原生提供了表单值修改方法,不需要额外维护本地state,直接修改Formik的表单值即可:
login.tsx修改后代码:
import { FormikProps } from "formik"; export interface FormValues { title: string; } export const Login: React.FC<FormikProps<FormValues>> = (props) => { // 从Formik props中提取setFieldValue方法 const { handleSubmit, handleBlur, handleChange, touched, errors, values, setFieldValue } = props; useEffect(() => { fetch("https://jsonplaceholder.typicode.com/todos/1") .then((response) => response.json()) .then((json) => { // 直接修改Formik对应字段的值 setFieldValue('title', json.title); }); }, [setFieldValue]); // 原有渲染逻辑保持不变即可 return ( <Container component="main" maxWidth="xs"> <div className={classes.paper}> <form className={classes.form} noValidate onSubmit={handleSubmit}> <TextField variant="outlined" margin="normal" required fullWidth id="title" label="Title" name="title" value={values.title} autoFocus autoComplete="off" onChange={handleChange} onBlur={handleBlur} /> <Button type="submit" fullWidth variant="contained" color="primary" className={classes.submit} > Sign In </Button> </form> </div> </Container> ); };
该方案不需要修改HOC层代码,修改后直接生效。
方案2:把初始值作为props透传给HOC(适合初始值来自上层组件的场景)
如果你的接口请求是在上层组件发起的,可以把拿到的初始值作为props传给LoginView,利用mapPropsToValues自动同步:
1. 修改login.hoc.tsx代码:
import { Form, FormikProps, FormikValues, useFormik, withFormik } from "formik"; import { FormValues, Login } from "./index"; // 扩展HOC接收的props,添加初始值字段 interface MyFormikProps { initialTitle?: string; } export const LoginView = withFormik<MyFormikProps, FormValues>({ enableReinitialize: true, mapPropsToValues: (props) => { // 从props获取初始值,无值则用空字符串兜底 return { title: props.initialTitle || "" }; }, handleSubmit: (values) => { console.log(values); }, })(Login);
2. 上层组件调用时传入初始值即可:
// 上层组件示例代码 const App = () => { const [initialTitle, setInitialTitle] = useState('') useEffect(() => { fetch("https://jsonplaceholder.typicode.com/todos/1") .then(res => res.json()) .then(json => setInitialTitle(json.title)) }, []) return <LoginView initialTitle={initialTitle} /> }
内容的提问来源于stack exchange,提问作者RRR uzumaki
相关产品推荐
相关产品推荐

