[英]How to pass all state values to number of child components and update the parent
[英]How to update parent state and child components props at once (at the same time)
我是 React 的新手,基本上我正在嘗試一次更新父App.js
組件的 state 及其子組件( Team.js
和Player.js
)道具。 目前只有父組件的 state 正在更新。 我將嘗試一步一步地更好地解釋它。
這里我有一個父組件App.js
export default function App() {
const teams = [
{
Name: "Chicago Bulls",
Players: ["Michael Jordan", "Dennis Rodman", "Scottie Pippen"],
Championships: 6
},
{
Name: "Golden State Warriors",
Players: ["Stephen Curry", "Klay Thompson", "Draymond Green"],
Championships: 5
},
{
Name: "Los Angeles Lakers",
Players: ["Kobe Bryant", "LeBron James", "Magic Johnson"],
Championships: 17
}
];
const [selectedTeam, setSelectedTeam] = useState({});
const players = [
{ Name: "LeBron James", MVPs: 4 },
{ Name: "Michael Jordan", MVPs: 5 },
{ Name: "Stephen Curry", MVPs: "2" }
];
const [selectedPlayer, setSelectedPlayer] = useState({});
const [modalContent, setModalContent] = useState(false);
const clickedComponent = useRef(null);
const [show, setShowModal] = useState(false);
const showModal = () => {
setShowModal(true);
};
const hideModal = () => {
setShowModal(false);
};
const handleModalContent = (clicked) => {
switch (clicked) {
case "Team":
clickedComponent.current = (
<Team
teams={teams}
selectedTeam={selectedTeam}
setSelectedTeam={setSelectedTeam}
/>
);
break;
case "Player":
clickedComponent.current = (
<Player
players={players}
selectedPlayer={selectedPlayer}
setSelectedPlayer={setSelectedPlayer}
/>
);
break;
default:
clickedComponent.current = null;
break;
}
};
return (
<div className="App" style={{ justifyContent: "space-evenly" }}>
<div
style={{
justifyContent: "center",
width: "100%",
display: "flex",
flexWrap: "wrap",
margin: "40px 0px 0px 0px"
}}
>
<div
className="table-cell"
onClick={() => {
handleModalContent("Team");
setModalContent(true);
showModal();
}}
>
<div className="table-cell-text">Click to access Team component</div>
</div>
<div
className="table-cell"
onClick={() => {
handleModalContent("Player");
setModalContent(true);
showModal();
}}
>
<div className="table-cell-text">
Click to access Player component
</div>
</div>
</div>
<h3 style={{ marginTop: "30px" }}>
The last selected team was: {selectedTeam.Name}
<br />
The last selected player was: {selectedPlayer.Name}
</h3>
<Modal show={show} modalClosed={hideModal}>
{(modalContent && clickedComponent.current) || null}
</Modal>
</div>
);
}
該組件有兩個 arrays 對象( teams
和players
),分別作為道具發送到Team
和Player
組件。 Team
還接收selectedTeam
和setSelectedTeam
作為道具。 Player
接收selectedPlayer
和setSelectedPlayer
。 這兩個組件都有一個Modal
組件和一個 select 輸入。 在Team
組件中,用戶將 select 一個團隊,他們將顯示所選球隊的球員,而在Player
組件中,一個球員將為 select 並顯示所選球員的 MVP 數量。
Team.js
const Team = (props) => {
return (
<div style={{ position: "relative", margin: "0 auto", width: "10em" }}>
<h3>Select a team</h3>
<div className="input-group col">
<select
onChange={(e) => {
if (e === "") props.setSelectedTeam({});
else {
let foundTeam = props.teams.find(
(team) => team.Name === e.target.value
);
props.setSelectedTeam(foundTeam);
}
}}
>
<option value="">Select a team...</option>
{props.teams.map((team) => (
<option key={team.Name} value={team.Name}>
{team.Name}
</option>
))}
</select>
</div>
{Object.keys(props.selectedTeam).length > 0 ? (
<div>
<h3>{props.selectedTeam.Name} players: </h3>
<br />
{props.selectedTeam.Players.map((player, index) => (
<div key={index}>{player}</div>
))}
</div>
) : null}
</div>
);
};
export default Team;
Player.js
const Player = (props) => {
return (
<div style={{ position: "relative", margin: "0 auto", width: "10em" }}>
<h3>Select a player</h3>
<div className="input-group col">
<select
onChange={(e) => {
if (e === "") props.setSelectedPlayer({});
else {
let foundPlayer = props.players.find(
(player) => player.Name === e.target.value
);
props.setSelectedPlayer(foundPlayer);
}
}}
>
<option value="">Select a player...</option>
{props.players.map((player) => (
<option key={player.Name} value={player.Name}>
{player.Name}
</option>
))}
</select>
</div>
{Object.keys(props.selectedPlayer).length > 0 ? (
<div>
<h3>
{props.selectedPlayer.Name} MVPs: {props.selectedPlayer.MVPs}
</h3>
</div>
) : null}
</div>
);
};
export default Player;
所以我的問題是,如果我 select 是子組件中的一個選項,他們不會立即收到更新的選定選項(我的意思是Team
組件的selectedTeam
和Player
組件的selectedPlayer
),但在父組件App
中我更新了它們。 所以,如果我想讓它們得到更新,我需要 select 一個選項,關閉模式並再次重新打開它們。
例如,這里我有App.js
視覺對象:
如果我打開Team.js
和 select 一個團隊,我selectedTeam
了在App.js
中更新的團隊,但在Team.js
中沒有:
因此,如果我關閉模式並再次重新打開Team
組件,那么我更新了props.selectedTeam
。 所以我有以下內容:
我對Player
組件有同樣的問題,但在這種情況下,關於props.selectedPlayer
我怎樣才能讓它正常工作,我的意思是,我怎樣才能在App
中同時更新props.selectedTeam
和props.selectedPlayer
,例如分別在Team
和Player
中? 謝謝!
代碼沙盒
https://codesandbox.io/s/young-sun-gs117?file=/src/Team.js:51-1127
我知道的方法是只使用 Hooks useState
和useEffect
並在 select 更改上更新 state 。
希望下面的Player
示例有所幫助(在您的代碼沙箱中工作,除非我沒有回答您的問題):
import React, { useState, useEffect } from "react";
import "./styles.css";
const Player = (props) => {
const [test, setTest] = useState("");
useEffect(() => {
console.log("props:", props);
setTest(props.selectedPlayer);
}, [props]);
return (
<div style={{ position: "relative", margin: "0 auto", width: "10em" }}>
<h3>Select a player</h3>
<div className="input-group col">
<select
value={props.selectedPlayer}
onChange={(e) => {
if (e === "") props.setSelectedPlayer({});
else {
let foundPlayer = props.players.find(
(player) => player.Name === e.target.value
);
props.setSelectedPlayer(foundPlayer);
setTest(foundPlayer);
}
}}
>
<option value="">Select a player...</option>
{props.players.map((player) => (
<option key={player.Name} value={player.Name}>
{player.Name}
</option>
))}
</select>
</div>
<h3>{test.Name} MVPs: {test.MVPs}</h3>
{/* {Object.keys(props.selectedPlayer).length > 0 ? (
<div>
<h3>
{props.selectedPlayer.Name} MVPs: {props.selectedPlayer.MVPs}
</h3>
</div>
) : null} */}
</div>
);
};
export default Player;
這是你需要做的,我重構了你的代碼並添加了一些注釋,這樣你就知道我做了什么。 要記住的一件事是,您幾乎不想將組件存儲在 state 中。
export default function App() {
const teams = [
{
Name: "Chicago Bulls",
Players: ["Michael Jordan", "Dennis Rodman", "Scottie Pippen"],
Championships: 6,
},
{
Name: "Golden State Warriors",
Players: ["Stephen Curry", "Klay Thompson", "Draymond Green"],
Championships: 5,
},
{
Name: "Los Angeles Lakers",
Players: ["Kobe Bryant", "LeBron James", "Magic Johnson"],
Championships: 17,
},
];
const players = [
{ Name: "LeBron James", MVPs: 4 },
{ Name: "Michael Jordan", MVPs: 5 },
{ Name: "Stephen Curry", MVPs: "2" },
];
// This makes typo mistake less and will give you auto complete option
const componentType = {
team: "Team",
player: "Player",
};
const [selectedTeam, setSelectedTeam] = useState({});
const [selectedPlayer, setSelectedPlayer] = useState({});
// the modalContent state and show state are doing the same thing so one of them is unneccessary
const [show, setShowModal] = useState(false);
const [clickedComponent, setClickedComponent] = useState("");
const showModal = () => {
setShowModal(true);
};
const hideModal = () => {
setShowModal(false);
};
const handleModalContent = (clicked) => {
setClickedComponent(clicked);
};
return (
<div className="App" style={{ justifyContent: "space-evenly" }}>
<div
style={{
justifyContent: "center",
width: "100%",
display: "flex",
flexWrap: "wrap",
margin: "40px 0px 0px 0px",
}}
>
<div
className="table-cell"
onClick={() => {
handleModalContent(componentType.team);
showModal();
}}
>
<div className="table-cell-text">Click to access Team component</div>
</div>
<div
className="table-cell"
onClick={() => {
handleModalContent(componentType.player);
showModal();
}}
>
<div className="table-cell-text">
Click to access Player component
</div>
</div>
</div>
<h3 style={{ marginTop: "30px" }}>
The last selected team was: {selectedTeam.Name}
<br />
The last selected player was: {selectedPlayer.Name}
</h3>
<Modal show={show} modalClosed={hideModal}>
{clickedComponent === componentType.player ? (
<Player
players={players}
selectedPlayer={selectedPlayer}
setSelectedPlayer={setSelectedPlayer}
/>
) : clickedComponent === componentType.team ? (
<Team
teams={teams}
selectedTeam={selectedTeam}
setSelectedTeam={setSelectedTeam}
/>
) : null}
</Modal>
</div>
);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.