Я играю с крючками React и столкнулся с проблемой. Он показывает неправильное состояние, когда я пытаюсь утешить его с помощью кнопки, обработанной прослушивателем событий.
CodeSandbox: https://codesandbox.io/s/lrxw1wr97m
- Нажмите кнопку "Добавить карту" 2 раза
- На первой карте нажмите на кнопку 1 и увидите в консоли, что в состоянии 2 карты (правильное поведение)
- В первой карте нажмите кнопку Button2 (обрабатывается прослушивателем событий) и увидите в консоли, что в состоянии только одна карта (неправильное поведение)
Почему это показывает неправильное состояние? В первой карте Button2 должен отображать 2 карты в консоли. Есть идеи?
import React, { useState, useContext, useRef, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const CardsContext = React.createContext();
const CardsProvider = props => {
const [cards, setCards] = useState([]);
const addCard = () => {
const id = cards.length;
setCards([...cards, { id: id, json: {} }]);
};
const handleCardClick = id => console.log(cards);
const handleButtonClick = id => console.log(cards);
return (
<CardsContext.Provider
value={{ cards, addCard, handleCardClick, handleButtonClick }}
>
{props.children}
</CardsContext.Provider>
);
};
function App() {
const { cards, addCard, handleCardClick, handleButtonClick } = useContext(
CardsContext
);
return (
<div className="App">
<button onClick={addCard}>Add card</button>
{cards.map((card, index) => (
<Card
key={card.id}
id={card.id}
handleCardClick={() => handleCardClick(card.id)}
handleButtonClick={() => handleButtonClick(card.id)}
/>
))}
</div>
);
}
function Card(props) {
const ref = useRef();
useEffect(() => {
ref.current.addEventListener("click", props.handleCardClick);
return () => {
ref.current.removeEventListener("click", props.handleCardClick);
};
}, []);
return (
<div className="card">
Card {props.id}
<div>
<button onClick={props.handleButtonClick}>Button1</button>
<button ref={node => (ref.current = node)}>Button2</button>
</div>
</div>
);
}
ReactDOM.render(
<CardsProvider>
<App />
</CardsProvider>,
document.getElementById("root")
);