reactjs - 使用钩子将状态从一个组件传递到另一个(不是子组件)
问题描述
我的搜索栏在一个Navbar
组件中,该组件与所有屏幕都是一致的,所以它在我的App.js
文件中。现在,我想存储用户在 Input (in Navbar.jsx
) 中输入的字符串,将其带到App.js
然后将其传递给我的其他组件。我不知道该怎么做。给出了我正在谈论的三个文件:
App.js
(包含Navbar
和我的其他组件的文件)Navbar.jsx
(包含我们从中获取字符串的输入搜索栏的文件)Homepage.jsx
(我要访问搜索栏字符串以过滤我的结果的页面)
应用程序.js
import "./App.css";
import {
Navbar,
Homepage,
Crypto,
Exchanges,
Settings,
} from "./components/index";
import { Layout } from "antd";
import Dock from "./components/Dock/Dock";
import { Switch, Route } from "react-router-dom";
function App() {
return (
<div className="App">
<div className="navbar">
<Navbar />
<Dock />
</div>
<div className="main">
<Layout>
<div className="routes>">
<Switch>
<Route exact path="/">
<Homepage />
</Route>
<Route exact path="/cryptocurrencies">
<Crypto />
</Route>
<Route exact path="/exchanges">
<Exchanges />
</Route>
<Route exact path="/settings">
<Settings />
</Route>
</Switch>
</div>
</Layout>
</div>
</div>
);
}
export default App;
主页.jsx
import React, { useState, useEffect } from "react";
import "./Homepage.css";
import CryptoCard from "../Card/Card";
import axios from "axios";
const Homepage = () => {
const [coinData, setCoinData] = useState([], () => {
const localData = localStorage.getItem("coinData");
return localData ? JSON.parse(localData) : [];
});
useEffect(() => {
const options = {
method: "GET",
url: "https://coinranking1.p.rapidapi.com/coins",
headers: {
"x-rapidapi-host": "coinranking1.p.rapidapi.com",
"x-rapidapi-key": "API_KEY",
},
};
axios
.request(options)
.then((response) => {
setCoinData(response.data.data.coins);
// persist in localStorage
localStorage.setItem(
"coinData",
JSON.stringify(response.data.data.coins)
);
})
.catch((error) => {
console.error(error);
});
}, []);
console.log("Coins names");
coinData.forEach(function (coin) {
console.log(coin.name);
});
return (
<div className="homepage">
<div className="heading">
<h1>Discover</h1>
<hr className="line" />
</div>
<div className="cards-container">
{(coinData || []).map((coin) => (
<CryptoCard
name={coin.name}
coinUrl={coin.websiteUrl}
duration="4 minutes ago"
symbol={coin.symbol}
rank={coin.rank}
exchanges={coin.numberOfExchanges}
price={coin.price}
/>
))}
</div>
</div>
);
};
export default Homepage;
导航栏.jsx
import React, { useState, useEffect } from "react";
import AppBar from "@mui/material/AppBar";
import Box from "@mui/material/Box";
import Toolbar from "@mui/material/Toolbar";
import IconButton from "@mui/material/IconButton";
import Badge from "@mui/material/Badge";
import MenuItem from "@mui/material/MenuItem";
import Menu from "@mui/material/Menu";
import AccountCircle from "@mui/icons-material/AccountCircle";
import NotificationsIcon from "@mui/icons-material/Notifications";
import MoreIcon from "@mui/icons-material/MoreVert";
import Icon from "../../images/logo.png";
import Brightness3Icon from "@mui/icons-material/Brightness3";
import WbSunnyTwoToneIcon from "@mui/icons-material/WbSunnyTwoTone";
import "./Navbar.css";
import HomeIcon from "@mui/icons-material/Home";
var notification = 1;
export default function PrimarySearchAppBar() {
const [darkMode, setDarkMode] = useState(true);
const darkModeToggle = () => {
setDarkMode(!darkMode);
};
useEffect(() => {
if (darkMode) {
document.body.classList.add("dark");
} else {
document.body.classList.remove("dark");
}
}, [darkMode]);
const [anchorEl, setAnchorEl] = React.useState(null);
const [mobileMoreAnchorEl, setMobileMoreAnchorEl] = React.useState(null);
const isMenuOpen = Boolean(anchorEl);
const isMobileMenuOpen = Boolean(mobileMoreAnchorEl);
const handleProfileMenuOpen = (event) => {
setAnchorEl(event.currentTarget);
};
const handleMobileMenuClose = () => {
setMobileMoreAnchorEl(null);
};
const handleMenuClose = () => {
setAnchorEl(null);
handleMobileMenuClose();
};
const handleMobileMenuOpen = (event) => {
setMobileMoreAnchorEl(event.currentTarget);
};
const menuId = "primary-search-account-menu";
const renderMenu = (
<Menu
anchorEl={anchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
id={menuId}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
open={isMenuOpen}
onClose={handleMenuClose}
>
<MenuItem onClick={handleMenuClose}>Profile</MenuItem>
<MenuItem onClick={handleMenuClose}>My account</MenuItem>
</Menu>
);
const mobileMenuId = "primary-search-account-menu-mobile";
const renderMobileMenu = (
<Menu
anchorEl={mobileMoreAnchorEl}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
id={mobileMenuId}
keepMounted
transformOrigin={{
vertical: "top",
horizontal: "right",
}}
open={isMobileMenuOpen}
onClose={handleMobileMenuClose}
>
<MenuItem>
<IconButton size="large" color="inherit" style={{ marginTop: "3px" }}>
{"day" === "night" ? (
<Brightness3Icon style={{ color: "#000000" }} />
) : (
<WbSunnyTwoToneIcon style={{ color: "#000000" }} />
)}
</IconButton>
{"day" === "night" ? <p>Dark Mode</p> : <p> Light Mode</p>}
</MenuItem>
<MenuItem>
<IconButton
size="large"
aria-label="show 17 new notifications"
color="inherit"
>
<Badge badgeContent={notification} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<p>Notifications</p>
</MenuItem>
<MenuItem onClick={handleProfileMenuOpen}>
<IconButton
size="large"
aria-label="account of current user"
aria-controls="primary-search-account-menu"
aria-haspopup="true"
color="inherit"
>
<AccountCircle />
</IconButton>
<p>Profile</p>
</MenuItem>
<MenuItem>
<IconButton size="large" aria-haspopup="true" color="inherit">
<HomeIcon />
</IconButton>
<p>Home</p>
</MenuItem>
</Menu>
);
//RENDERING ON SCREEN
return (
<div className="navbar-container">
<Box sx={{ flexGrow: 1 }}>
<AppBar
position="static"
style={{ background: "#171721" }}
elevation={0}
>
<Toolbar>
<img src={Icon} alt="alt" className="app-logo" />
<Box sx={{ flexGrow: 1 }} />
<div className="search">
<input
type="text"
placeholder="Find your Exchange or Currency..."
className="search-bar"
/>
</div>
<Box sx={{ flexGrow: 1 }} />
<Box sx={{ display: { xs: "none", md: "flex" } }}>
<IconButton size="large" color="inherit">
{darkMode === true ? (
<a className="mode" onClick={darkModeToggle}>
<WbSunnyTwoToneIcon style={{ color: "#B7B7BA" }} />
</a>
) : (
<a className="mode" onClick={darkModeToggle}>
<Brightness3Icon style={{ color: "#B7B7BA" }} />
</a>
)}
</IconButton>
<IconButton
size="large"
aria-label="show 17 new notifications"
color="inherit"
style={{ color: "#B7B7BA" }}
>
<Badge badgeContent={notification} color="error">
<NotificationsIcon />
</Badge>
</IconButton>
<IconButton
size="large"
edge="end"
aria-label="account of current user"
aria-controls={menuId}
aria-haspopup="true"
onClick={handleProfileMenuOpen}
color="inherit"
style={{ color: "#B7B7BA" }}
>
<AccountCircle />
</IconButton>
</Box>
<Box sx={{ display: { xs: "flex", md: "none" } }}>
<IconButton
size="large"
aria-label="show more"
aria-controls={mobileMenuId}
aria-haspopup="true"
onClick={handleMobileMenuOpen}
color="inherit"
>
<MoreIcon />
</IconButton>
</Box>
</Toolbar>
</AppBar>
{renderMobileMenu}
{renderMenu}
</Box>
</div>
);
}
如何将状态从Navbar
to传递App
到 my Homepage
?
不是问题的一部分,但如果您对如何从map
主页中的功能过滤结果有任何见解,请告诉我。将不胜感激!
解决方案
您可以简单地在 App.js 中声明该状态并将其用作组件 Navbar 和 Homepage 中的道具
应用程序.js
import "./App.css";
import {
Navbar,
Homepage,
Crypto,
Exchanges,
Settings,
} from "./components/index";
import { Layout } from "antd";
import Dock from "./components/Dock/Dock";
import { Switch, Route } from "react-router-dom";
function App() {
const [searchValue, setSearchValue] = useState("");
return (
<div className="App">
<div className="navbar">
<Navbar searchValue={searchValue} setSearchValue={setSearchValue}/>
<Dock />
</div>
<div className="main">
<Layout>
<div className="routes>">
<Switch>
<Route exact path="/">
<Homepage setSearchValue={setSearchValue} searchValue={searchValue}/>
...
);
}
export default App;
主页.jsx
const Homepage = ({setSearchValue, searchValue}) => {
...
导航栏.jsx
const Navbar= ({setSearchValue, searchValue}) => {
...
如果你有更多的组件要处理甚至是孙子,使用 props 可能是多余的,所以我建议你学习 redux 或 useContext 钩子来管理你的状态
推荐阅读
- html - 如何防止仅绝对定位的元素发送链接?
- tomcat - 使用 SSL 登录 GeoServer 的问题
- python - 聚合熊猫数据框但折叠重复的单元格值
- c# - .NET5 连接的 Wsdl 服务未按预期填充响应
- javascript - 如何在 angular-flot 条上添加 onclick 功能
- node.js - 将变量传递给views子文件夹中的ejs模板文件
- python - ValueError:折叠数必须是 Integral 类型。[数组([[0.25, 0.
- html - 响应式图片弹性库
- oracle - 如何使用 Oracle.jl 删除 oracle 表?
- php - 如何检查日期('H:i:s')是否大于夜间时间且小于一天的开始时间?