使用 redux-form 和 react-select.creatable 为啥模糊事件会清除输入?
Posted
技术标签:
【中文标题】使用 redux-form 和 react-select.creatable 为啥模糊事件会清除输入?【英文标题】:with redux-form and react-select.creatable why does a blur event clear the input?使用 redux-form 和 react-select.creatable 为什么模糊事件会清除输入? 【发布时间】:2018-08-04 16:48:55 【问题描述】:我正在使用:
反应 15.6.2 redux-form 7.2.0 反应选择 1.2.1我还没有为此设置代码笔,这很复杂。希望有人会单独从源头上看到问题。我可以做梦,不是吗?
我有一个 redux-form
显示一个 invoice
对象:
invoice = client: email: 'someguy@somewhere.com'
总结:我使用react-select.creatable
作为电子邮件下拉列表的自动完成组件。选择email
会在invoice
上设置client
。
当我创建一个新的电子邮件地址并选择它,然后模糊输入字段时,输入值被清除。
invoice
表单上的新 client
仍然在 redux 存储中正确设置,它只是从字段的输入值中清除。为什么?
请注意,根据其他答案,我已经使用正确的值从 Select
手动调用 input.onBlur()。我认为这与创建新选项有关。
// 包装自定义自动完成组件的 redux-form 字段
const clientOptions = clients.map(client => ( label: client.email, value: client ))
const isValidNewOption = ( label ) => email.REG_EMAIL.test(label)
const promptTextCreator = (label) => (Send to $label
)
const newOptionCreator = (label, labelKey, valueKey) =>
返回标签:标签,值:电子邮件:标签
// RFReactSelect,一个react-select 可创建作为自动完成功能,能够创建一个新选项
import React, PropTypes from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
RFReactSelect.defaultProps =
multi: false,
className: ""
;
RFReactSelect.propTypes =
input: PropTypes.shape(
name: PropTypes.string.isRequired,
onBlur: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func.isRequired,
).isRequired,
options: PropTypes.array.isRequired,
multi: PropTypes.bool,
className: PropTypes.string,
onNewOptionClick: PropTypes.func,
;
export default function RFReactSelect(props)
const input , options, multi, className,
newOptionCreator, promptTextCreator, isValidNewOption = props
const name, value, onBlur, onChange, onFocus = input;
const transformedValue = transformValue(value, options, multi);
return (
<Select.Creatable
className=className
isValidNewOption=isValidNewOption
name=name
multi=multi
newOptionCreator=newOptionCreator
onSelectResetsInput=false
onBlurResetsInput=false
options=options
onChange=multi
? multiChangeHandler(onChange)
: singleChangeHandler(onChange)
onBlur=() => onBlur(value)
onFocus=onFocus
promptTextCreator=promptTextCreator
value=transformedValue
valueKey='value'
/>
);
/**
* onChange from Redux Form Field has to be called explicity.
*/
function singleChangeHandler(func)
return function handleSingleChange(value)
func(value ? value.value : '');
;
/**
* onBlur from Redux Form Field has to be called explicity.
*/
function multiChangeHandler(func)
return function handleMultiHandler(values)
func(values.map(value => value.value));
;
/**
* For single select, Redux Form keeps the value as a string, while React Select
* wants the value in the form value: "grape", label: "Grape"
*
* * For multi select, Redux Form keeps the value as array of strings, while React Select
* wants the array of values in the form [ value: "grape", label: "Grape" ]
*/
function transformValue(value, options, multi)
if (multi && typeof value === 'string') return [];
const filteredOptions = options.filter(option =>
return multi
? value.indexOf(option.value) !== -1
: option.value === value;
);
return multi ? filteredOptions : filteredOptions[0];
【问题讨论】:
【参考方案1】:我解决了。问题是您必须跟踪本地状态下新创建的选项,并将它们与组件的props.options
连接起来,否则新选项在重新渲染时会丢失。所以value
传回Field
的onBlur
为空。这是来源:
import React, Component, PropTypes from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
class RFReactSelect extends Component
constructor()
super()
this.state =
createdOptions: []
this.onNewOptionClick = this.onNewOptionClick.bind(this)
render()
const input , options, multi, className,
newOptionCreator, promptTextCreator, isValidNewOption = this.props
const name, value, onBlur, onChange, onFocus = input;
const allOptions = options.concat(this.state.createdOptions)
const transformedValue = this.transformValue(value, allOptions, multi);
return (
<Select.Creatable
className=className
isValidNewOption=isValidNewOption
multi=multi
name=name
newOptionCreator=newOptionCreator
onSelectResetsInput=false
onBlurResetsInput=false
options=allOptions
onChange=multi
? this.multiChangeHandler(onChange)
: this.singleChangeHandler(onChange)
onBlur=() => onBlur(value)
onFocus=onFocus
onNewOptionClick=this.onNewOptionClick
promptTextCreator=promptTextCreator
ref='creatable'
value=transformedValue
valueKey='value'
/>
);
/**
* Keep created options in local state or they will be lost
* on re-render
*/
onNewOptionClick(option)
const props, select = this.refs.creatable
const options = props
options.unshift(option)
select.selectValue(option)
this.setState(
createdOptions: [option]
)
/**
* onChange from Redux Form Field has to be called explicity.
*/
singleChangeHandler(func)
return function handleSingleChange(option)
func(option ? option.value : '');
;
/**
* onBlur from Redux Form Field has to be called explicity.
*/
multiChangeHandler(func)
return function handleMultiHandler(values)
func(values.map(value => value.value));
;
/**
* For single select, Redux Form keeps the value as a string, while React Select
* wants the value in the form value: "grape", label: "Grape"
*
* * For multi select, Redux Form keeps the value as array of strings, while React Select
* wants the array of values in the form [ value: "grape", label: "Grape" ]
*/
transformValue(value, options, multi)
if (multi && typeof value === 'string') return [];
const filteredOptions = options.filter(option =>
return multi
? value.indexOf(option.value) !== -1
: option.value === value;
);
return multi ? filteredOptions : filteredOptions[0];
RFReactSelect.defaultProps =
multi: false,
className: ""
;
RFReactSelect.propTypes =
input: PropTypes.shape(
name: PropTypes.string.isRequired,
onBlur: PropTypes.func.isRequired,
onChange: PropTypes.func.isRequired,
onFocus: PropTypes.func.isRequired,
).isRequired,
options: PropTypes.array.isRequired,
multi: PropTypes.bool,
className: PropTypes.string,
onNewOptionClick: PropTypes.func,
export default RFReactSelect
【讨论】:
你能为这个例子创建一个沙箱吗?以上是关于使用 redux-form 和 react-select.creatable 为啥模糊事件会清除输入?的主要内容,如果未能解决你的问题,请参考以下文章
使用 React-intl 的 Redux-form 字段级验证和错误翻译
使用 axios 和 redux-thunk 以 redux-form 发布请求
如何使用 redux-form 在不同组件(向上一个组件)中显示 FieldArray 中的字段