#reactjs #react-hooks
Вопрос:
Я пытаюсь создать динамический раскрывающийся список с помощью начальной загрузки. Элементы в этом раскрывающемся списке будут меняться в зависимости от значения, выбранного в предыдущем раскрывающемся списке. Значение в предыдущем раскрывающемся списке успешно изменяется, и состояние также изменяется, но {Имя пользователя} не отображается повторно после каждого выбора.
const users = ... // API call from server
const [userName, setUserName] = useState([]);
useEffect(() => {
console.log(userName) // userName successfully changes at each select
}, [userName]);
function handleSelect(event) {
setUserName(event.target.value)
}
return (
...
<Form.Group>
<Form.Label>
Select User
</Form.Label>
// This part works fine
<Form.Control
as="select"
onChange={handleSelect}
className="form-select"
>
{users.map(names => {
<option key={names.value} > {names.name} </option>
}
</Form.Control>
<Dropdown>
// userName doesnt change
<Dropdown.Item> {userName} </Dropdown.Item>
<Dropdown>
...
)
Комментарии:
1. Я не понимаю, если
userName
useEffect
он обновился при входе в систему, это то же значение, которое использовалось при возврате рендеринга. Другими словами, это значение состояния для этого цикла визуализации. Можете ли вы создать работающий код и поле, воспроизводящее эту проблему, в котором мы можем проверять и отлаживать в режиме реального времени?2. можете ли вы предоставить codesandbox для этого ?
3. Почему вы устанавливаете свое начальное состояние в виде массива? если это только одно имя пользователя
Ответ №1:
Примечание https://reactjs.org/docs/hooks-reference.html#usestate
В отличие от метода setState, найденного в компонентах класса, useState не объединяет объекты обновления автоматически. Вы можете повторить это поведение, объединив форму средства обновления функций с синтаксисом распространения объектов:
function handleSelect(event) {
setUserName((prevValues) => return [...prevValues, event.target.value])
}
Комментарии:
1. Я думаю, что массив в качестве начального состояния является ошибкой, поскольку пользовательский интерфейс отображает
select
ввод, а обработчик изменений обрабатывает только одно значение. И тот факт, что правильное значение зарегистрировано вuseEffect
крючке, является подсказкой о том, что состояние обновляется правильно, как и ожидалось.
Ответ №2:
Я использовал тот же код, который вы предоставили, и он работает для меня.
Может быть, этот фрагмент поможет вам.
// Get a hook function
const { useState, useEffect, Fragment } = React;
const { Form, Dropdown, Row, Col, Container } = ReactBootstrap;
const Example = ({}) => {
const [userName, setUserName] = useState([]);
const users = [
{ name: "abc", value: "abc" },
{ name: "xyz", value: "xyz" }
];
function handleSelect(event) {
setUserName(event.target.value);
}
return (
<Container>
<Row>
<Col sm={6}>
<Form.Label>Select User</Form.Label>
<Form.Control as="select" onChange={handleSelect} className="form-select">
{users.map((val) => {
return <option key={val.value}> {val.name} </option>;
})}
</Form.Control>
</Col>
</Row>
<Row>
<Form.Label>Selected Value:</Form.Label>
<Dropdown>
<Dropdown.Item>{userName}</Dropdown.Item>
</Dropdown>
</Row>
</Container>
);
};
// Render it
ReactDOM.render(<Example title="Example using Hooks:" />, document.getElementById("react"));
<link
rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.0/dist/css/bootstrap.min.css"
integrity="sha384-B0vP5xmATw1 K9KRQjQERJvTumQW0nPEzvF6L/Z6nronJ3oUOFUFpCjEUQouq2 l"
crossorigin="anonymous"
/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<script
src="https://unpkg.com/react-bootstrap@next/dist/react-bootstrap.min.js"
crossorigin></script>
<div id="react"></div>