[英]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.