如何在 React.js 中使用 react-router-dom 保持 App() 级别状态不重置?
Posted
技术标签:
【中文标题】如何在 React.js 中使用 react-router-dom 保持 App() 级别状态不重置?【英文标题】:How do I keep App() level state from resetting with react-router-dom in React.js? 【发布时间】:2021-06-04 12:19:35 【问题描述】:我有一个钩子可以改变我的应用程序的背景颜色。我希望在浏览网站时背景颜色保持不变,但路由器将此状态重置回其原始 useState 的“白色”。如何正确实施?
使用 create-react-app 创建。
已编辑以显示最小可重现示例:
import React, useState from 'react';
import Route, Switch, BrowserRouter from 'react-router-dom';
import './App.css';
export default function App()
const [color, setColor] = useState('white');
function changeBackground(value)
setColor(value);
;
return (
<div className=color>
<BrowserRouter>
<Navbar changeBackground=changeBackground />
</BrowserRouter>
</div>
);
;
function Navbar(props)
return (
<div>
<button onClick=() => props.changeBackground('red')>
Change Background Color
</button>
<div>
<a href="/page1">Page 1</a>
</div>
<div>
<a href="/page2">Page2</a>
</div>
<Switch>
<Route exact path="/page1"><Page1 /></Route>
<Route exact path="/page2"><Page2 /></Route>
</Switch>
</div>
);
;
function Page1()
return (
<div>
Page 1
</div>
);
;
function Page2()
return (
<div>
Page 2
</div>
);
;
/* App.css */
.white
background-color: white;
.red
background-color: red;
添加最小可重现示例之前的先前代码:
import React, useState from 'react';
import Route, Switch, BrowserRouter from 'react-router-dom';
import './App.css';
import './assets/fonts/fonts.css';
import Navbar from './components/Navbar';
import Design from './components/Design';
import Develop from './components/Develop';
import Else from './components/Else';
import DesignTest from './pages/DesignTest';
function App()
const [backgroundColor, setBackgroundColor] = useState('white');
function changeBackground(value)
setBackgroundColor(value);
;
return (
<div className=`w-screen min-h-screen $backgroundColor`>
/* <Router> */
<Navbar changeBackground=changeBackground />
<BrowserRouter>
<Switch>
<Route exact path="/"></Route>
<Route exact path="/design"><Design /></Route>
<Route exact path="/develop"><Develop /></Route>
<Route exact path="/else"><Else /></Route>
<Route exact path="/design/test"><DesignTest /></Route>
</Switch>
</BrowserRouter>
</div>
);
export default App;
function Navbar(props)
return (
<div className="w-screen h-screen inline-grid grid-cols-12 grid-rows-6 tuffyBold tracking-widest">
<div className="row-start-1 row-end-3 col-start-1 col-end-7 text-right mt-auto mb-auto text-5xl">
TITLE
</div>
<div className="row-start-3 row-end-4 col-start-7 col-end-13 test-left mt-auto mb-auto text-4xl">
<a href="/design">
DESIGN
</a>
</div>
<div className="row-start-4 row-end-5 col-start-7 col-end-13 test-left mt-auto mb-auto text-4xl">
<a href="/develop">
DEVELOP
</a>
</div>
<div className="row-start-5 row-end-7 col-start-7 col-end-13 test-left mt-auto mb-auto text-4xl">
<a href="/else">
EVERY<br />THING<br />ELSE
</a>
</div>
<div className="row-start-1 row-end-3 col-start-7 col-end-13 mt-auto mb-auto ml-auto mr-auto">
<div className="circle white" onClick=() => props.changeBackground('white')></div>
</div>
<div className="row-start-3 row-end-4 col-start-1 col-end-7 mt-auto mb-auto ml-auto mr-auto">
<div className="circle yellow" onClick=() => props.changeBackground('yellow')></div>
</div>
<div className="row-start-4 row-end-5 col-start-1 col-end-7 mt-auto mb-auto ml-auto mr-auto">
<div className="circle blue" onClick=() => props.changeBackground('blue')></div>
</div>
<div className="row-start-5 row-end-6 col-start-1 col-end-7 mt-auto mb-auto ml-auto mr-auto">
<div className="circle dark" onClick=() => props.changeBackground('dark')></div>
</div>
</div>
);
export default Navbar;
.yellow
background-color: #CDB900;
color: black;
.blue
background-color: #009CCD;
color: black;
.dark
background-color: #4B394E;
color: white;
.white
background-color: white;
color: black;
【问题讨论】:
你能分享Navbar
吗?
这并不能解决您的问题,但如果它只是要调用 setBackgroundColor
,则您不需要 changeBackground
函数。您可以直接传递 setBackgroundColor。
【参考方案1】:
当我单击导航栏以更改路线时,我遇到了相同的应用程序状态刷新问题。原来是因为没有使用react router提供的Link组件造成的。
就我而言,我使用的是引导导航栏组件。我从引导站点获得的代码创建了这样的导航栏链接:
<Nav.Link href="/home">Home</Nav.Link>
通过“href”的导航是这里的问题。所以为了克服这个问题,我将 Nav.Link 包裹在 LinkContainer 中。这使我可以从 Nav.Link 中删除 href,并使用 LinkContainer 中的“to”属性提供了路由 url。
<LinkContainer to="/home">
<Nav.Link>Home</Nav.Link>
</LinkContainer>
为了使用 LinkContainer,我必须安装并导入它。
npm install react-router-bootstrap
import LinkContainer from "react-router-bootstrap";
【讨论】:
【参考方案2】:我发现了我的问题。我使用 <a href="/#">
而不是从 react-router-dom 导入 Link
,导致整个页面重新渲染。这是我想要的版本:
import React, useState from 'react';
import Route, Switch, BrowserRouter, Link from 'react-router-dom';
import './App.css';
export default function App()
const [color, setColor] = useState('white');
function changeBackground(value)
setColor(value);
;
return (
<div className=color>
<BrowserRouter>
<Navbar changeBackground=changeBackground />
</BrowserRouter>
</div>
);
;
function Navbar(props)
return (
<div>
<button onClick=() => props.changeBackground('red')>
Change Background Color
</button>
<div>
<Link to="/page1">Page 1</Link>
</div>
<div>
<Link to="/page2">Page2</Link>
</div>
<Switch>
<Route exact path="/page1"><Page1 /></Route>
<Route exact path="/page2"><Page2 /></Route>
</Switch>
</div>
);
;
function Page1()
return (
<div>
Page 1
</div>
);
;
function Page2()
return (
<div>
Page 2
</div>
);
;
/* App.css */
.white
background-color: white;
.red
background-color: red;
【讨论】:
这个答案对我有用。我用它来解决我遇到的同样的问题。就我而言,问题是由于使用了使用 href 的引导导航栏组件而发生的。我还提供了我的解决方案作为答案,以防它对其他人有帮助。【参考方案3】:似乎有什么东西触发了重新渲染整个应用程序。可能 React 开发者工具可以帮助你在代码中找到那个地方。
我创建了一个孤立的例子 - https://codesandbox.io/s/solitary-wood-8oi66?fontsize=14&hidenavigation=1&theme=dark&file=/src/App.js
在这个例子中,钩子中的颜色值也保存到浏览器LocalStorage中,并用作第一次渲染的默认值,因此可以在重新加载页面后保持背景颜色。也许这就是您想要实现的目标。但我不确定。
const defaultColor = localStorage.getItem("bgColor");
const [backgroundColor, setBackgroundColor] = useState(
defaultColor || "white"
);
function changeBackground(value)
setBackgroundColor(value);
localStorage.setItem("bgColor", value);
【讨论】:
【参考方案4】:因为您的Navbar
在路由器组件之外,这意味着您单击的所有内容实际上是在重新加载页面,而不是被 react-router 捕获。在浏览器路由器中移动导航栏组件:
return (
<div className=`w-screen min-h-screen $backgroundColor`>
/* <Router> */
<BrowserRouter>
<Navbar changeBackground=changeBackground />
<Switch>
<Route exact path="/"></Route>
<Route exact path="/design"><Design /></Route>
<Route exact path="/develop"><Develop /></Route>
<Route exact path="/else"><Else /></Route>
<Route exact path="/design/test"><DesignTest /></Route>
</Switch>
</BrowserRouter>
</div>
);
【讨论】:
感谢您的关注。我进行了更改,但每当我在网站上的任何位置导航时,背景颜色仍会变回“白色”。 你能创建一个minimal, reproducible example吗? 更新了最小可重复的例子。以上是关于如何在 React.js 中使用 react-router-dom 保持 App() 级别状态不重置?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 node.js 中导入 font-awesome 以在 react.js 中使用?
如何在 React.js 中使用 JavaScript 修改 CSS