【问题标题】:Resetting the redux store when routing other components in React在 React 中路由其他组件时重置 redux 存储
【发布时间】: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;

【问题讨论】:

    标签: reactjs react-redux react-router-dom


    【解决方案1】:

    您的商店状态的重置是由两个问题的组合引起的:

    首先,由于您没有根据当前 URL 对 React Store 的状态进行水合,因此您必须以某种方式保存和加载 Store 的状态以在页面加载之间保留它。

    您可以通过简单地将 URL 复制并粘贴到新的浏览器窗口来模拟此问题;您会注意到商店状态已重置。存储状态的方法有很多种,您可能希望使用 sessionStorage(在您的应用位于浏览器选项卡上时保留)或 localStorage(在您的应用清除它之前保留)。

    其次,您在不期望的情况下获得页面加载的原因是您似乎没有正确使用 React Router。

    您正在使用 Bootstrap 的导航栏链接,其行为类似于普通的 &lt;a&gt; 锚标记。单击 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 组件。即&lt;Link to="/main"&gt;Access Survey Portal&lt;/Link&gt;
    • 感谢@Alan,感谢您的评论,这(stackoverflow.com/questions/54843302/…)解决了我的问题。
    • 明白了。这个&lt;Nav.Link as={Link} to="/main" &gt;Access Survey Portal&lt;/Nav.Link&gt;
    • 对于 NavDropdown,您可以使用 React Routers history.push 以编程方式在点击处理程序内重定向。要访问历史记录,您可以使用 useHistory 挂钩。
    猜你喜欢
    • 1970-01-01
    • 2020-03-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-27
    • 1970-01-01
    • 2020-05-26
    • 2018-09-04
    相关资源
    最近更新 更多