繁体   English   中英

如何保持 App() 级别 state 在 React.js 中使用 react-router-dom 重置?

[英]How do I keep App() level state from resetting with react-router-dom in React.js?

我有一个钩子可以改变我的应用程序的背景颜色。 我希望在浏览站点时背景颜色保持不变,但路由器将此 state 重置为其原始使用状态“白色”。 我该如何正确实施?

使用 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; }

我发现了我的问题。 我使用<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; }

当我单击导航栏更改路线时,我遇到了同样的完整应用程序 state 刷新问题。 原来问题是由于没有使用 react 路由器提供的 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";

因为您的导航栏位于路由器组件之外,这意味着您单击的所有内容实际上都是在重新加载页面,而不是被Navbar捕获。 在浏览器路由器中移动导航栏组件:

  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>
  );

似乎某些东西触发了重新渲染整个应用程序。 可能 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);
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM