如何使用redux-thunk与useSelector实现数据加载完成后再填充表单
Redux-thunk + useSelector 表单数据回填解决方案
前置修改:给Redux状态增加加载标识
你需要在存储表单数据的Redux切片中,新增loading、error两个状态,用来标记异步请求的状态:
// reducer 示例代码 const initialState = { formData: undefined, // 要填充的表单数据 loading: false, // 请求加载状态 error: null // 请求错误信息 } function formReducer(state = initialState, action) { switch(action.type) { case 'FETCH_FORM_DATA_START': return {...state, loading: true, error: null} case 'FETCH_FORM_DATA_SUCCESS': return {...state, loading: false, formData: action.payload} case 'FETCH_FORM_DATA_FAILED': return {...state, loading: false, error: action.payload} default: return state } }
对应的thunk异步请求逻辑中,请求发起、成功、失败的节点分别dispatch对应的action即可。
方案1:等待数据加载完成再渲染表单(推荐)
在表单的父组件中同时读取loading、formData、error三个状态,只有请求完成、数据存在的情况下才渲染表单组件,保证表单初始化时就能拿到完整的初始值:
import { useSelector, useDispatch } from 'react-redux' import { useEffect } from 'react' import { fetchFormData } from './thunkActions' import UserForm from './UserForm' function FormContainer() { const dispatch = useDispatch() const { formData, loading, error } = useSelector(state => state.formSlice) // 组件挂载时触发数据请求 useEffect(() => { dispatch(fetchFormData()) }, [dispatch]) // 加载中展示占位内容 if (loading) return <div>数据加载中,请稍候</div> // 请求失败展示错误提示 if (error) return <div>数据加载失败,请刷新重试</div> // 数据存在时才渲染表单,传入初始值 return formData ? <UserForm initialValues={formData} /> : null }
该方案可以规避表单初始化无值、后续不更新的问题,因为表单组件是在数据就绪后才初始化的,initialValues会直接生效。
方案2:保留表单展示,监听数据变化手动回填
如果你需要始终展示表单,不需要加载占位,可以通过useEffect监听formData的变化,拿到数据后手动调用表单的赋值方法:
// 以Ant Design Form组件为例 import { Form, Input } from 'antd' import { useSelector } from 'react-redux' import { useEffect } from 'react' function UserForm() { const [form] = Form.useForm() const formData = useSelector(state => state.formSlice.formData) // 监听formData变化,存在值时手动回填表单 useEffect(() => { if (formData) { form.setFieldsValue(formData) } }, [formData, form]) return ( <Form form={form}> <Form.Item name="name" label="姓名"> <Input /> </Form.Item> <Form.Item name="phone" label="手机号"> <Input /> </Form.Item> {/* 其余表单项 */} </Form> ) }
如果是原生受控表单,直接将输入框的value绑定到formData对应的字段即可,状态更新时会自动重渲染刷新值。
注意事项
- 绝大多数表单库的
initialValues仅在组件初始化时读取一次,后续数据变更不会自动触发更新,因此不要直接给initialValues赋值formData?.xxx这种可选链写法,会出现初始值为空、后续不更新的问题。 - 请确保你的thunk异步逻辑正确,请求成功后确实dispatch了保存数据的action,否则useSelector无法监听到状态变化。
内容的提问来源于stack exchange,提问作者Maykel
相关产品推荐
相关产品推荐

