在 React 中路由其他组件时重置 redux 存储
Posted
技术标签:
【中文标题】在 React 中路由其他组件时重置 redux 存储【英文标题】:Resetting the redux store when routing other components in React 【发布时间】:2021-07-28 04:28:18 【问题描述】:使用 react-router-dom、react-redux,我尝试实现一个网站。该网站已根据使用 redux 商店的语言设置显示内容。点击导航栏中的语言区域时,回调changeLanguage
函数,然后改变商店的语言状态,网站正确显示改变语言的内容。但是,当我单击导航栏中的其他链接“/home”或“/main”时,它会登陆页面,resetting the redux store。可以告诉我如何处理这个问题吗?
语言切片
import createSlice from "@reduxjs/toolkit";
export const languageSlice = createSlice(
name: "language",
initialState:
language: "Fr",
,
reducers:
getLanguage: (state, action) =>
return state;
,
changeLanguage: (state, action) =>
if (action.payload == "En")
return
...state,
language: "Fr",
;
else
return
...state,
language: "En",
;
,
,
);
export const getLanguage, changeLanguage = languageSlice.actions;
export default languageSlice.reducer;
store.js
import configureStore from "@reduxjs/toolkit";
import languageSlice from "./languageSlice";
export default configureStore(
reducer:
languageSlice: languageSlice,
,
);
LanguageService.js
import getLanguage, changeLanguage from "../app/languageSlice";
export const changeLan = (dispatch, language) =>
dispatch(changeLanguage(language));
;
export const getLan = (dispatch) =>
dispatch(getLanguage());
;
Index.jsx
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import App from "./App";
import reportWebVitals from "./reportWebVitals";
import store from "./app/store";
import Provider from "react-redux";
import "bootstrap/dist/css/bootstrap.min.css";
ReactDOM.render(
<React.StrictMode>
<Provider store=store>
<App />
</Provider>
</React.StrictMode>,
document.getElementById("root")
);
reportWebVitals();
App.jsx
import "./App.css";
import React, useEffect from "react";
import MainPage from "./MainPage";
import Home from "./Home";
import Switch, BrowserRouter, Redirect, Route from "react-router-dom";
import Navbar from "./layout/NavBar";
import Event from "./staticPages/Event";
import getLan from "./service/LanguageService";
import useDispatch, useSelector from "react-redux";
function App()
const dispatch = useDispatch();
const language = useSelector((state) => state.languageSlice.language);
useEffect(() =>
getLan(dispatch);
console.log(language);
, [language]);
return (
<div
className=" ml-auto mr-auto"
style=
width: "80%",
>
<BrowserRouter>
<Navbar />
<Switch>
<Route exact path="/home" render=() => <Home /> />
<Route exact path="/main" render=() => <MainPage /> />
<Route exact path="/event" render=() => <Event /> />
<Route component=() => <h3>Page is not found!</h3> />
</Switch>
<Footer />
</BrowserRouter>
</div>
);
export default App;
导航栏
import Nav, Navbar, NavDropdown, Image from "react-bootstrap";
import React, useState, useEffect from "react";
import useDispatch, useSelector from "react-redux";
import changeLan, getLan from "../service/LanguageService";
const NavBar = () =>
const dispatch = useDispatch();
const language = useSelector((state) => state.languageSlice.language);
const changeLanguage = () =>
changeLan(dispatch, language);
;
return (
<>
<Navbar collapseOnSelect expand="sm">
<Navbar.Brand href="/home">
Home
</Navbar.Brand>
<Nav onSelect=changeLanguage>
<Nav.Item>
<Nav.Link href="#">language</Nav.Link>
</Nav.Item>
</Nav>
<Navbar.Toggle aria-controls="responsive-navbar-nav" />
<Navbar.Collapse id="responsive-navbar-nav">
<Nav className="ml-auto" light="true">
<NavDropdown title="Events" id="nav-dropdown1">
<NavDropdown.Item href="/event">Latest Events</NavDropdown.Item>
</NavDropdown>
<Nav.Item>
<Nav.Link href="/main">Access Survey Portal</Nav.Link>
</Nav.Item>
</Nav>
</Navbar.Collapse>
</Navbar>
</>
);
;
export default NavBar;
事件页面
import React from "react";
import useSelector from "react-redux";
const Event = () =>
const language = useSelector((state) => state.languageSlice.language);
return (
<>
language != "En" ? (
<div className="area">
<section
className="product_landing_welcome_area product_landing jarallax my-auto"
id="home"
style= backgroundColor: "#008fac"
>
<div className="container h-100">
<div className="row align-items-center">
<div className="col-sm col-md-12 col-lg-12 text-center">
<div
className="welcome_text_area m-top-3"
style=
width: "100%",
paddingBottom: "35px",
paddingTop: "35px",
marginBottom: "0px",
>
<h3 className="fonts-shadow-into-light text-white">
<b>Latest Events</b>
</h3>
</div>
</div>
</div>
</div>
</section>
</div>
) : (
<div className="area">
<section
className="product_landing_welcome_area product_landing jarallax my-auto"
id="home"
style= backgroundColor: "#008fac"
>
<div className="container h-100">
<div className="row align-items-center">
<div className="col-sm col-md-12 col-lg-12 text-center">
<div
className="welcome_text_area m-top-3"
style=
width: "100%",
paddingBottom: "35px",
paddingTop: "35px",
marginBottom: "0px",
>
<h3 className="fonts-shadow-into-light text-white">
<b>Événements récents</b>
</h3>
</div>
</div>
</div>
</div>
</section>
</div>
)
</>
);
;
export default Event;
【问题讨论】:
【参考方案1】:您的商店状态的重置是由两个问题的组合引起的:
首先,由于您没有根据当前 URL 对 React Store 的状态进行水合,因此您必须以某种方式保存和加载 Store 的状态以在页面加载之间保留它。
您可以通过简单地将 URL 复制并粘贴到新的浏览器窗口来模拟此问题;您会注意到商店状态已重置。存储状态的方法有很多种,您可能希望使用 sessionStorage(在您的应用位于浏览器选项卡上时保留)或 localStorage(在您的应用清除它之前保留)。
其次,您在不期望的情况下获得页面加载的原因是您似乎没有正确使用 React Router。
您正在使用 Bootstrap 的导航栏链接,其行为类似于普通的 <a>
锚标记。单击 Nav.Link 会指示您的浏览器进行 HTTP GET 调用,并执行页面加载以重置商店。
相反,您需要覆盖 Bootstrap Nav Link 组件以使用 React Routers Link 组件,该组件不会进行页面加载,而是加载正确的 React 模块。
https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage https://reactrouter.com/web/api/Link
【讨论】:
感谢您的评论。顺便说一句,您能否解释一下“相反,您需要覆盖 Bootstrap Nav Link 组件以使用 React Routers Link 组件,该组件不会进行页面加载,而是加载正确的 React 模块。”详细点? 将 NavBar 组件中的Nav.Link
组件替换为 react-router-dom 中的 Link
组件。即<Link to="/main">Access Survey Portal</Link>
感谢@Alan,感谢您的评论,这(***.com/questions/54843302/…)解决了我的问题。
明白了。这个<Nav.Link as=Link to="/main" >Access Survey Portal</Nav.Link>
对于 NavDropdown,您可以使用 React Routers history.push
以编程方式在点击处理程序内重定向。要访问历史记录,您可以使用 useHistory
挂钩。以上是关于在 React 中路由其他组件时重置 redux 存储的主要内容,如果未能解决你的问题,请参考以下文章
在将 react-router 5 与 redux 7 一起使用时,react-router <Link> 在转到新路由后不会重置状态