#javascript #reactjs #react-hooks
#javascript #reactjs #реагирующие хуки
Вопрос:
Рассмотрим следующий пример. Я вызываю функцию выборки в родительском из дочернего.
Запрос завершается, я передаю данные из асинхронного запроса в мой Child
as items
prop. Я устанавливаю его как значение по умолчанию для useState
— React.useState(items);
.
Ожидаемое поведение: запрос завершается, items
обновляется, Child
получает новые реквизиты, его повторный рендеринг и значение по умолчанию в useState
обновляется. Таким a
образом, переменная содержит соответствующий объект.
Фактическое поведение: значение по умолчанию в useState
не обновляется между визуализациями. Почему?
const Child = ({ fn, items }) => {
const [a, b] = React.useState(items);
console.log(a, items); // a is null but items is an object
React.useEffect(() => {
fn();
}, []);
return JSON.stringify(a);
}
const App = () => {
const [stateOne, setStateOne] = React.useState(null);
const fn = () => {
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(response => response.json())
.then(json => {
setStateOne(json);
});
}
console.log(stateOne)
return <Child fn={fn} items={stateOne} />;
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root"></div>
Комментарии:
1.
fetch()
является асинхронным.console()
нет. Таким образом,fetch();console.log(fetchresults);
, почти всегда пусто, если ваша сеть не FTL.2. @HoldOffHunger Спасибо, но в этом примере это не так.
3. исправьте соглашение об именовании
const [a, setA] = React.useState(items);
Ответ №1:
Значение по умолчанию намеренно используется только при монтировании компонента. Это то, что подразумевается под «по умолчанию». После этого единственный способ изменить состояние — вызвать функцию установки состояния ( b
в вашем коде).
Редко бывает, что вам нужно копировать prop в state, поэтому вероятным решением является просто полное удаление состояния и использование prop.
const Child = ({ fn, items }) => {
React.useEffect(() => {
fn();
}, []);
return JSON.stringify(items);
}
Если вам по какой-то причине необходимо иметь состояние, сначала подумайте, можете ли вы переместить это состояние до родительского и, таким образом, устранить эту проблему. Если по какой-то причине вы тоже не можете этого сделать, то вам потребуется, чтобы дочерняя логика реализации вызывала установщик состояния b
, когда вы хотите, чтобы он был вызван. Например:
const Child = ({ fn, items }) => {
const [a, b] = React.useState(items);
React.useEffect(() => {
b(items);
}, [items]);
React.useEffect(() => {
fn();
}, []);
return JSON.stringify(a);
}
Комментарии:
1. Итак, как только компонент смонтирован, он никогда не изменится, если только компонент не будет размонтирован и смонтирован снова, да?
2. Да, значение по умолчанию будет использовано ровно один раз, когда компонент монтируется. Если вы размонтируете и перемонтируете, вы получите новый элемент, который будет использовать его значение по умолчанию (которое может отличаться от того, что было у старого элемента).
Ответ №2:
Вы неправильно поняли, что значит иметь «значение по умолчанию» в случае реактивных перехватов. Это не столько «значение по умолчанию», сколько «начальное значение».
Рассмотрим следующий код:
let n = Math.random();
const [myN, setMyN] = useState(n);
console.log(n) // This number will always be the same between renders
В вашем случае начальное значение равно null
. Оно никогда не изменится, если только вы не вызовете для него установщик.
Если вы хотите передать prop, не смешивайте его с state .