#reactjs #react-select
#reactjs #реагировать-выбрать
Вопрос:
Я использую react-select
для одного меню выбора. defaultValue
Кажется, что при редактировании формы отображается правильно, но при отправке формы возвращается значение, undefined
если выбор оставлен без изменений. Если я нажму defaultValue
, то при отправке он будет работать правильно. Есть ли что-то еще, чего prop
мне не хватает для поддержки defaultValue
сквозной отправки?
Код выглядит следующим образом:
<Select
closeMenuOnSelect={true}
options={options()}
defaultValue={defaultVal}
className="basic-single"
classNamePrefix="select"
/>
Где options()
есть простая функция для форматирования данных следующим образом:
const options = [
{ value: "chocolate", label: "Chocolate" },
{ value: "strawberry", label: "Strawberry" },
{ value: "vanilla", label: "Vanilla" }
];
И defaultVal
возвращает единственное значение путем фильтрации options
:
let defaultVal = options().filter(
(optionChoice) => optionChoice.label === props.choice
);
Ответ №1:
Поскольку вы используете react-hook-form
, вам необходимо использовать их Controller
компонент для регистрации вашего выбора в форме. Ссылка здесь: Интеграция управляемых входных данных.
Следующее объявление компонента иллюстрирует перенос react-select
компонента в react-hook-form
компонент контроллера. Оно регистрируется с помощью react-hook-form с помощью control={control}
, а затем отображает выбор через render prop компонента контроллера.
Вам также необходимо react-hook-form
сообщить, когда выбор изменится, вызвав handleChange
из select on change. handleChange()
в свою очередь вызывает react-hook-form
setValue()
с измененным значением и shouldDirty: true
помечает изменение.
const handleChange = (change) => {
setValue("controlledSelect", change, {
shouldDirty: true
});
};
Рабочая среда здесь:https://codesandbox.io/s/react-select-with-react-hook-form-im9hi
import React from "react";
import { useForm, Controller } from "react-hook-form";
import Select from "react-select";
function ControlledSelect() {
const { handleSubmit, control, setValue } = useForm();
const [options, setOptions] = React.useState(initialOptions);
const onSubmitData = (data) => {
console.log(data);
};
const handleChange = (change) => {
setValue("controlledSelect", change, {
shouldDirty: true
});
};
return (
<div className="container">
<form onSubmit={handleSubmit(onSubmitData)}>
<Controller
name="controlledSelect"
control={control}
defaultValue={options[1]}
render={() => (
<Select
options={options}
defaultValue={options[1]}
onChange={handleChange}
/>
)}
/>
<button type="submit">Submit Select</button>
</form>
</div>
);
}
Вот примерный фрагмент, показывающий рабочий выбор. Похоже, вы хотите объявить defaultValue
как индекс в массиве: defaultValue={defaultVal[0]}
. Это потребует создания вашего массива форматированных параметров перед визуализацией, а не передачи функции, что, вероятно, лучше в любом случае.
<script src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/emotion@9.2.12/dist/emotion.umd.min.js"></script>
<script src="https://unpkg.com/prop-types@15.5.10/prop-types.min.js"></script>
<script src="https://unpkg.com/react-input-autosize@2.2.1/dist/react-input-autosize.min.js"></script>
<script src="https://unpkg.com/react-select@2.1.2/dist/react-select.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.min.js"></script>
<div id="App"></div>
<script type="text/babel">
const {useRef} = React;
const options = [
{ value: 'chocolate', label: 'Chocolate' },
{ value: 'strawberry', label: 'Strawberry' },
{ value: 'vanilla', label: 'Vanilla' }
]
function App() {
const formRef = useRef();
const submitForm = (e, ref) => {
e.preventDefault();
console.log(formRef.current.elements[1].value);
}
return (
<form ref={formRef} onSubmit={submitForm}>
<Select
name="select"
options={options}
defaultValue={options[1]}
/>
<input type="submit" value="Submit" />
</form>
)
}
ReactDOM.render(<App />, document.getElementById('App'));
</script>
Комментарии:
1.
options
Находятся в функции, потому что они получены из массива, который необходимо сопоставить сvalue
/label
. Даже при этомdefaultValue
работает и отображается вconsole
, но при отправке значение равноundefined
. Я также используюreact-hook-form
, поэтому я не уверен, может ли это быть частью проблемы.2. Да,
react-hook-form
что-то меняет. Я отредактировал свой ответ для объяснения и связал рабочий codesandbox.3. спасибо, у меня была большая часть того, что вы включили помимо
handleChange
функции. Я все еще не могу заставить его работать, но я думаю, что это может быть связано с сохранениемoptions
как функции. Я собираюсь попытаться сохранить параметры, используяuseState
хук, как вы это сделали.4. Мне не хватало одной вещи — я включал только
defaultValue
prop в<Select/>
, но не в<Controller/>
. Как только я это сделал, остальное сработало. ПочемуdefaultValue
необходимо дублировать в родительском и дочернем компонентах?5. Это два отдельных компонента. На самом деле вы можете исключить его из любого из них, но у каждого есть свои последствия: если вы оставите его вне выбора, то начальное значение не будет установлено, но контроллер будет иметь (скрытое) начальное значение; если вы оставите контроллер, выбор будет отображать начальное значение, но пока вы не измените выбор (не запустите onChange), контроллер будет пустым. В конечном счете, именно контроллер отправляет значения, а Select предоставляет интерфейс. Рад, что у вас получилось!