#reactjs #react-hooks #use-state #use-context
#reactjs #реагирующие хуки #use-state #использование-context
Вопрос:
Я пытался обновить состояние после того, как пользователь выберет выпадающий список, однако выбранный параметр никогда не изменяется. Смотрите gif — https://recordit.co/KH2Pqn34bp .
Я смущен тем, что в идеале после использования setFilterOptions
для обновления состояния предполагается повторно отобразить этот компонент с новым значением, но этого не происходит. Кто-нибудь может помочь взглянуть? Чего мне здесь не хватает? Большое спасибо!
Пример кода в изолированной среде — https://codesandbox.io/s/react-select-default-value-forked-1ybdk?file=/index.js
const SearchFilter = () => {
const [filterOptions, setFilterOptions] = useContext(SearchFilterContext);
let curSort = filterOptions['sortType'] || DEFAULT_SORT_OPTION;
const handleSortChange = (option) => {
setFilterOptions(previous => Object.assign(previous, { 'sortType': option }))
};
return (
<span className='filter-container'>
<Select options={SORT_TYPE_OPTIONS} value={curSort} onChange={handleSortChange}/>
</span>
);
};
Комментарии:
1. Можете ли вы предоставить минимальный, воспроизводимый пример? Я предполагаю, что вы не используете
onChange
prop внутриSelect
компонента.2. @Yousaf Я пытался получить это в песочнице — codesandbox.io/s/react-select-default-value-forked-1ybdk?file =/… , надеюсь, это было бы полезно.
3. @Yousaf не могли бы вы немного подробнее объяснить, как не использовать
onChange
prop? ПотомуhandleSortChange
что это в основном метод onChange, который содержитsetFilterOptions
.
Ответ №1:
Пара проблем в вашем коде:
- Чтобы установить значение
Select
компонента по умолчанию, вы написали ненужный код. Вместо этого вы можете просто использоватьdefaultValue
prop для установки значенияSelect
компонента по умолчанию.<Select options={OPTIONS} defaultValue={OPTIONS[0]} onChange={handleSortChange} />
- Вы изменяете состояние напрямую.
Object.assign(...)
возвращаетtarget
объект. В вашем случае целевым объектом является предыдущее состояние.Вместо возврата нового объекта состояния вы изменяете состояние напрямую и возвращаете предыдущий объект состояния, что предотвращает повторный рендеринг.
Используя
spread-syntax
, вы можете корректно обновить состояние, как показано ниже:const handleSortChange = (option) => { setFilterOptions({ ...filterOptions, sortType: option }); };
Следующий код устраняет вышеупомянутую проблему в вашем компоненте:
const SearchFilter = () => {
const [filterOptions, setFilterOptions] = useState({});
const handleSortChange = (option) => {
setFilterOptions({ ...filterOptions, sortType: option });
};
return (
<span className="filter-container">
<Select
options={OPTIONS}
defaultValue={OPTIONS[0]}
onChange={handleSortChange}
/>
</span>
);
};
Ответ №2:
Причина, по которой вы не видите изменений, заключается в том, что этот функциональный компонент будет повторно отображаться только тогда, когда увидит, что ваше состояние изменилось (на основе вашего сценария изолированной среды). В тот момент, когда вы используете Object.assign(previous, { 'sortType': option})
, вы меняете sortType
свойство в объекте, но сам объект не изменяется, и поэтому функциональный компонент не видит изменений.
Мы можем решить эту проблему, используя либо Object.assign({}, previous, { 'sortType': option})
, который создаст НОВЫЙ объект с предыдущими атрибутами состояния и измененным типом сортировки (первый параметр Object.assign — это объект, в который будут скопированы следующие свойства объекта. если мы используем пустой объект, который является эквивалентом нового объекта) или мы можем использовать оператор распространения и заменить его на ({...sortType, 'sortType': option})
который также создаст новый объект, который функциональный компонент распознает как измененное значение состояния.
const handleSortChange = (option) => {
setFilterOptions(previous => Object.assign({}, previous, { 'sortType': option }))
};
или
const handleSortChange = (option) => {
setFilterOptions(previous => ({...previous, 'sortType': option})
};
Имейте в виду, что это мелкие копии объектов.
Комментарии:
1. Большое спасибо, вы спасли мой день!! Я не знал, что
Object.assign(previous, { 'sortType': option})
ссылка не изменяется…2. Нет проблем, рад, что смог помочь!