如何使用redux-form的formValueSelector()获取按钮值并实现动态表单
解决redux-form动态表单按钮触发字段显示及formValueSelector使用问题
首先说清楚为什么你用Field渲染按钮不生效:
Field组件是用来绑定表单输入控件的,它的核心逻辑是监听控件的值变化来更新redux-form的表单状态。但普通按钮(type='button')本身没有可绑定的“值变化”事件——点击按钮不会改变按钮的value或checked状态,所以Field不会触发任何redux-form的状态更新,自然无法像复选框那样触发动态显示字段的逻辑。
正确实现按钮点击显示字段的两种方式
方式一:组件内部维护状态(无需提交该状态)
如果“是否显示字段”的状态不需要随表单一起提交,直接用组件自身的状态控制最方便:
import { useState } from 'react'; import { Field, reduxForm } from 'redux-form'; // 自定义字段渲染组件 const renderInput = ({ input, label, meta: { touched, error } }) => ( <div> <label>{label}</label> <input {...input} /> {touched && error && <span className="error">{error}</span>} </div> ); const DynamicForm = ({ handleSubmit }) => { // 用useState控制是否显示额外字段 const [showTargetField, setShowTargetField] = useState(false); return ( <form onSubmit={handleSubmit}> {/* 基础字段 */} <Field name="username" component={renderInput} type="text" label="用户名" /> {/* 触发按钮 */} <button type="button" onClick={() => setShowTargetField(true)} style={{ margin: '10px 0' }} > 显示手机号字段 </button> {/* 动态显示的字段 */} {showTargetField && ( <Field name="phone" component={renderInput} type="tel" label="手机号" /> )} <button type="submit">提交表单</button> </form> ); }; export default reduxForm({ form: 'dynamicForm' })(DynamicForm);
方式二:将状态存入redux-form表单(需提交该状态)
如果需要把“是否显示字段”的状态也作为表单数据提交,就用redux-form的change action来更新表单字段:
import { connect } from 'react-redux'; import { Field, reduxForm, change, formValueSelector } from 'redux-form'; const renderInput = ({ input, label, meta: { touched, error }, shouldShow }) => { // 根据传入的shouldShow控制显示 if (!shouldShow) return null; return ( <div> <label>{label}</label> <input {...input} /> {touched && error && <span className="error">{error}</span>} </div> ); }; const DynamicForm = ({ handleSubmit, dispatch, showPhoneField }) => { const handleShowField = () => { // 调用change action更新redux-form中的showPhoneField字段 dispatch(change('dynamicForm', 'showPhoneField', true)); }; return ( <form onSubmit={handleSubmit}> <Field name="username" component={renderInput} type="text" label="用户名" /> <button type="button" onClick={handleShowField} style={{ margin: '10px 0' }} > 显示手机号字段 </button> {/* 传递shouldShow属性控制显示 */} <Field name="phone" component={renderInput} type="tel" label="手机号" shouldShow={showPhoneField} /> <button type="submit">提交表单</button> </form> ); }; // 创建表单选择器 const formSelector = formValueSelector('dynamicForm'); // 从redux state中获取showPhoneField的值 const mapStateToProps = (state) => ({ showPhoneField: formSelector(state, 'showPhoneField') }); // 连接redux并导出 export default connect(mapStateToProps)(reduxForm({ form: 'dynamicForm' })(DynamicForm));
如何用formValueSelector获取表单字段值
formValueSelector的核心是从redux的全局state中提取指定表单的字段值,步骤很清晰:
- 导入formValueSelector:从redux-form中导入这个工具函数
- 创建表单选择器实例:传入你的表单名称(就是reduxForm配置里的
form属性值) - 在mapStateToProps中获取字段值:调用选择器,传入redux state和要获取的字段名
- 作为props传递给组件:之后就能在表单组件中直接使用这个值了
比如上面例子中的这段代码:
// 创建表单选择器 const formSelector = formValueSelector('dynamicForm'); // 从redux state中获取showPhoneField的值 const mapStateToProps = (state) => ({ showPhoneField: formSelector(state, 'showPhoneField') });
这样就能拿到dynamicForm表单中showPhoneField字段的当前值,用来控制字段显示或者做其他逻辑。
内容的提问来源于stack exchange,提问作者D2DN
相关产品推荐
相关产品推荐

