#reactjs #react-hooks #state #render
#reactjs #реагирующие перехваты #состояние #рендеринг
Вопрос:
Я делаю небольшое обучающее приложение React с использованием перехватов. Вот пример: существует MainPage.js и у него есть 3 похожих дочерних компонента Card.js . У меня есть глобальное состояние на главной странице, и каждая карта имеет свое собственное локальное состояние. У каждой карты есть prop «id» из MainPage и clickButton func.
Когда я нажимаю кнопку на любой карте, выполняется 2 операции:
- Локальная переменная ‘clicked’ становится true .
- Вызывается функция из родительского компонента и присваивает значение глобальной переменной состояния ‘firstCard’.
Каждый файл содержит console.log() для тестирования. И когда я нажимаю кнопку, она показывает фактическую глобальную переменную «firstCard» и 3 раза false (значение переменной по умолчанию «clicked» в Card). Это означает, что главная страница компонента отображается после нажатия кнопки? И каждая карта также отображается со значением по умолчанию «clicked».
- Почему отображается MainPage componenet, ведь мы не используем переменную «firsCard», кроме console.log() ?
- Как сделать так, чтобы после нажатия любой кнопки произошли изменения в локальном состоянии компонента, и в то же время глобальная переменная состояния «firstCard» тоже изменилась, но без родительского компонента рендеринга (мы не используем в jsx переменную «firstCard»)
Спасибо за вашу помощь!
import Card from "../Card/Card";
const Main = () => {
const [cards, setCards] = useState([]);
const [firstCard, setFirstCard] = useState(null);
useEffect(() => {
setCards([1, 2, 3]);
}, []);
const onClickHandler = (id) => {
setFirstCard(id);
};
console.log(firstCard); // Showing corrrect result
return (
<div>
{cards.map((card, i) => {
return (
<Card
key={Date.now() i}
id={card}
clickButton={(id) => onClickHandler(id)}
></Card>
);
})}
</div>
);
};
import React, { useState } from "react";
const Card = ({ id, clickButton }) => {
const [clicked, setClicked] = useState(false);
const onClickHandler = () => {
setClicked(true);
clickButton(id);
};
console.log(clicked); // 3x false
return (
<div>
<h1>Card number {id}</h1>
<button onClick={() => onClickHandler()}> Set ID</button>
</div>
);
};
export default Card;
Комментарии:
1. похоже, вы хотите учиться. Я укажу вам на React.memo reactjs.org/docs/react-api.html#reactmemo
2. Повторный рендеринг вызывается использованием функции setter from
useState
. Поскольку вы изменяете переменную состояния, компонент повторно рендерится, чтобы изменения могли (потенциально) быть отражены в пользовательском интерфейсе.
Ответ №1:
У вас неправильное представление о том, как работает react.
Когда вы что-то меняете в состоянии, этот компонент будет повторно отображаться, независимо от того, используете ли вы эту переменную состояния при рендеринге или нет. Более того, react также рекурсивно перерисовывает все дочерние элементы этого компонента.
Теперь вы можете запретить повторный рендеринг дочерних элементов (хотя и не фактического компонента, в котором произошло обновление состояния) в некоторых случаях, для этого вы можете изучить React.memo
.
Тем не менее, до перехватов React существовал метод shouldComponentUpdate, который вы могли бы использовать для пропуска рендеринга в зависимости от изменения состояния или реквизита.
Комментарии:
1. Это правильный ответ. Это распространенное заблуждение, которое есть у многих людей, впервые знакомых с react. React не оптимизирует, не вызывая «render», он оптимизирует, сравнивая два разных результата «render» и изменяя только dif в DOM.
2. @giggo1604 да, звучит верно.