У меня возникла проблема с тем, как реквизиты взаимодействуют с состоянием, создаваемым хуками.
В приведенном ниже примере состояние, удерживаемое в хуке, всегда одно за этим, как определено в реквизитах.
Я думаю Я понимаю, почему это происходит. Жизненный цикл выглядит примерно так:
- Компонент рендеринга
handleClick
определяется с доступом к области действия на основе этого рендера - Нажатие кнопки извонки
handleClick
handleClick
по-прежнему имеют доступ только к той области, которая была определена в рендере, и поэтому items
по-прежнему пуст add
вызывается;состояние в родительском компоненте обновляется, но setHookItems
будет использовать состояние, которое было определено в подпорках, когда handleClick
было определено hookItems
получает значение items
, которое пусто
Это для первого рендера, но я думаю, что принцип применим ко всем остальным;обработчик щелчков имеет доступ только к области действия до добавления нового элемента и поэтому устанавливает состояние подключения на основе того, что он имеет в качестве состояния для items
.
Iможет быть ошибочным в моих предположениях о том, как это происходит, но кажется, что это согласуется с тем, что я вижу.
Итак, к фактическому вопросу;Как я могу обновить элемент в состоянии ловушки, основываясь на последних реквизитах, из какого-то рода обработчиков, а не на реквизитах во время последнего рендеринга?
const { useState } = React;
const App = ({items, add}) => {
const [hookItems, setHookItems] = React.useState([]);
const handleClick = () => {
add(Math.floor(Math.random() * 10));
setHookItems(items);
}
return (
<div>
<p><span class="title">All Items: </span>{items.map(x => (<span>{x}</span>))}</p>
<p><span class="title">Hook Items: </span>{hookItems.map(x => (<span>{x}</span>))}</p>
<button onClick={handleClick}>Add</button>
</div>
);
}
const Root = () => {
const [items, setItems] = useState([]);
return (
<div>
<App items={items} add={item => setItems([...items, item])} />
</div>
)
}
ReactDOM.render(
<Root />,
document.getElementById('app')
);
.title { display: inline-block; width: 100px; text-align: right; margin-right: 20px;}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.6/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.6/umd/react-dom.production.min.js"></script>
<div id="app"></div>