redux-form无法使用initialValues?组件内entityId无法传入mapStateToProps的解决办法
解决redux-form动态设置初始值的问题
我来帮你梳理下解决思路,你遇到的核心问题是没法在mapStateToProps里拿到组件内部的this.entityId,所以没法直接生成initialValues对吧?这里有两种靠谱的方案,看你的entityId来源来选:
方案一:如果entityId是组件的props(比如路由参数、父组件传值)
这种情况其实可以利用mapStateToProps的第二个参数ownProps,它能拿到组件的所有props,这样就能直接在里面计算出对应的实体作为初始值,再配合redux-form的enableReinitialize配置,就能实现动态更新初始值:
import { reduxForm, connect } from 'redux-form'; // 从redux状态和组件props中获取初始值 const mapStateToProps = (state, ownProps) => { // 从ownProps里拿到你的entityId const targetEntity = state.entities.groups.find(entity => entity.id === ownProps.entityId); return { initialValues: targetEntity }; }; class ShowGroup extends Component { // 你的组件逻辑... render() { return ( <form> <Field name="groupName" component="input" type="text" /> <Field name="groupDesc" component="textarea" /> </form> ); } } // 配置reduxForm,开启enableReinitialize让初始值变化时重新渲染表单 const ShowGroupForm = reduxForm({ form: 'ShowGroupForm', // 给你的表单起个唯一名字 enableReinitialize: true })(ShowGroup); // 连接redux export default connect(mapStateToProps)(ShowGroupForm);
这样一来,只要ownProps.entityId变化,mapStateToProps就会重新计算initialValues,enableReinitialize会自动让表单加载新的初始值。
方案二:如果entityId是组件内部状态(比如用户操作后存在state里)
这种情况mapStateToProps拿不到组件内部的state,那就用redux-form提供的initialize action来动态设置初始值:
import { reduxForm, initialize, connect } from 'redux-form'; // 先把所有实体数组从redux拿过来 const mapStateToProps = state => ({ groups: state.entities.groups }); // 绑定initialize action到组件props const mapDispatchToProps = dispatch => ({ setFormInitials: (formName, values) => dispatch(initialize(formName, values)) }); class ShowGroup extends Component { state = { entityId: 'default-id' // 假设这是你组件内部维护的id }; // 组件挂载后设置初始值 componentDidMount() { this.updateFormInitials(); } // 当entityId或者实体数组变化时,更新初始值 componentDidUpdate(prevProps, prevState) { if (prevState.entityId !== this.state.entityId || prevProps.groups !== this.props.groups) { this.updateFormInitials(); } } updateFormInitials() { const { groups, setFormInitials, pristine } = this.props; const targetGroup = groups.find(g => g.id === this.state.entityId); // 可选:如果不想覆盖用户已经输入的内容,可以判断表单是否未修改(pristine) if (targetGroup && pristine) { setFormInitials('ShowGroupForm', targetGroup); } } render() { return ( <form> <Field name="groupName" component="input" type="text" /> <Field name="groupDesc" component="textarea" /> </form> ); } } // 配置reduxForm,不用设置initialValues const ShowGroupForm = reduxForm({ form: 'ShowGroupForm' })(ShowGroup); export default connect(mapStateToProps, mapDispatchToProps)(ShowGroupForm);
这里的关键是用initialize action来手动给表单设置初始值,配合生命周期方法监听entityId的变化,及时更新表单数据。
注意事项
- 确保表单名称(
form配置项)和initialize调用时的名称完全一致,不然找不到对应的表单。 - 如果担心覆盖用户输入,可以用reduxForm传给组件的
pristineprops判断,只有表单未被修改时才重新初始化。
内容的提问来源于stack exchange,提问作者Arian
相关产品推荐
相关产品推荐

