ReactJS: Как обернуть реакцию-select в поле сокращения?
Я работаю над библиотекой react-select
и сталкиваюсь с некоторыми проблемами, я использую библиотеку redux-form
и импортирую из нее компонент <Field />
. Чтобы я мог отправлять значения через форму для обслуживания.
Моя проблема:
Ниже упомянутый код работает нормально, когда я использую default от реакции-select. Я могу выбрать значения из раскрывающегося списка, и значение будет выбрано даже при фокусировке, значение останется. Но выбранное значение не отправляется через форму из-за redux-form
, поэтому я обматываю компонент и использую <Field name="sample" component={RenderSelectInput} id="sampleEX" options={options} />
import React from 'react';
import Select from 'react-select';
import RenderSelectInput from './RenderSelectInput'; // my customize select box
var options = [{ value: 'one', label: 'One' }, { value: 'two', label: 'Two' }];
class SelectEx extends React.Component {
constructor() {
super();
this.state = { selectValue: 'sample' }
this.updateValue = this.updateValue.bind(this);
}
updateValue(newValue) {
this.setState({ selectValue: newValue })
}
render() {
return (
<div>
<Select name="select1" id="selectBox" value={this.state.selectValue} options={options} onChange={this.updateValue}/>
//This works but value won't submit ...
<Field name="sample" component={RenderSelectInput} id="sampleEX" options={options} />
//For this, selected value vanishes once I come out of component.
</div>
)
}
}
export default SelectEx;
Но когда я использую мой настроенный выбор (я обертываю, чтобы отправить значение из формы), компонент <Select>
может быть видимым в пользовательском интерфейсе даже для значений. Но не удалось выбрать значение из раскрывающегося списка..., если я выберу его, он отобразится в поле <Select>
, но при фокусировке он исчезнет. Пожалуйста, помогите мне...
Компонент RenderSelectInput:
import React from 'react';
import {Field, reduxForm} from 'redux-form';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
const RenderSelectInput = ({input, options, name, id}) => (
<div>
<Select {...input} name={name} options={options} id={id} />
</div>
)
export default RenderSelectInput;
Спасибо,
Шаш
Ответы
Ответ 1
При использовании react-select
с редукционной формой вам необходимо изменить поведение по умолчанию методов onChange
и onBlur
и вызвать метод redux-form
onChange
и onBlur
соответственно.
Итак, попробуйте следующее:
const RenderSelectInput = ({input, options, name, id}) => (
<Select
{...input}
id={id}
name={name}
options={options}
value={input.value}
onChange={(value) => input.onChange(value)}
onBlur={(value) => input.onBlur(value)}
/>
)
и используйте вышеуказанный компонент, например
<Field component={RenderSelectInput} />
Вызов метода redux-form
onBlur
, когда фокус удаляется из поля Select
, предотвратит потерю значения.
Ответ 2
Вот это сработало для меня,
import React, { Component } from 'react';
import Select from 'react-select';
import 'react-select/dist/react-select.css';
export default class RenderSelectInput extends Component {
onChange(event) {
if (this.props.input.onChange && event != null) {
this.props.input.onChange(event.value);
} else {
this.props.input.onChange(null);
}
}
render() {
const { input, options, name, id, ...custom } = this.props;
return (
<Select
{...input}
{...custom}
id={id}
name={name}
options={options}
value={this.props.input.value || ''}
onBlur={() => this.props.input.onBlur(this.props.input.value)}
onChange={this.onChange.bind(this)}
/>
);
}
}
это было извлечено отсюда: https://ashiknesin.com/blog/use-react-select-within-redux-form/
Ответ 3
Используйте это, которое работает отлично, и это также обрабатывает проверку избыточной формы.
import React, {Component} from 'react';
import Select from 'react-select';
import {FormGroup} from "reactstrap";
class CustomSelect extends Component {
render() {
const {meta: {touched, error}} = this.props;
const className = ' form-group mb-3 ${touched && error ? 'has-danger' : '' }';
return (
<FormGroup>
<Select
{...this.props}
value={this.props.input.value}
onChange={(value) => this.props.input.onChange(value)}
onBlur={() => this.props.input.onBlur(this.props.input.value)}
options={this.props.options}
placeholder={this.props.placeholder}
/>
<div className={className}>
<div className="text-help">
{touched ? error : ''}
</div>
</div>
</FormGroup>
);
Используйте компонент CustomSelect в компоненте поля избыточной формы как
<Field
name='country_name'
options={this.state.countries}
component={CustomSelect}
placeholder="Select your country"
/>
Ответ 4
Попробуйте установить для свойства onBlurResetInput
значение false.
Что-то вроде.
const SelectInput = ({input: { onChange, value }, options, name, id}) => (
<Select
name={name}
value={value}
options={options}
onChange={onChange}
onBlurResetsInput={false}
/>
)
Надеюсь, это поможет!
Ответ 5
Я должен был вызвать onBlur без каких-либо аргументов. Проблема с ответом Хардика заключалась в том, что он не работал в iPad (возможно, в других iOS или сенсорных устройствах. Я не смог проверить).
Событие onBlur автоматически запускается вместе с событием onChange в iPad. Это привело к тому, что выбранное значение вернулось к своему начальному значению. Поэтому мне пришлось вызывать метод onBlur следующим образом:
onBlur = {(value) => input.onBlur()}
const RenderSelectInput = ({input, options, name, id}) => (
<Select
{...input}
id={id}
name={name}
options={options}
value={input.value}
onChange={(value) => input.onChange(value)}
onBlur={(value) => input.onBlur()}
/>
)
и используется как,
<Field component={RenderSelectInput} />