当前位置: 首页 > 知识库问答 >
问题:

在我的React应用中,为什么这个Redux reducer没有被执行?

范哲
2023-03-14

下午好,

在做了React教程,并阅读了所有React指南之后,我做了Redux教程来重新编写我的工作身份验证组件,以使用Redux而不是组件状态(我也从类切换到了功能组件)。

我的还原设置如下:

import { createSlice } from '@reduxjs/toolkit';

const sessionInitialState = {
        authToken: null,
        userLogin: null,
    };

export const sessionSlice = createSlice({
  name: 'session',
  initialState: {
    value: sessionInitialState,
  },
  reducers: {
    sessionRegister: (state, action) => {
      console.log("Storing:")
      console.log(action.payload)
      state.value = action.payload;
    },
    sessionDestroy: state => {
      console.log("Destroying session")
      state.value = sessionInitialState;
      localStorage.removeItem("sessionData");
    },
  },
});

export const { sessionRegister, sessionDestroy } = sessionSlice.actions;
export const selectSession = state => state.session.value;

export default sessionSlice.reducer;

在我的登录组件中,我存储了身份验证令牌和用户名,如下所示:

// [...]
import { useDispatch } from 'react-redux';
import { sessionRegister } from './SessionSlice';
// [...]

function LoginForm(props) {
    const dispatch = useDispatch();
    function onFormSubmit(event) {
        // [...] This is when API response code is 200:
        
                let sessionData = {
                        authToken: response.data.token,
                        userLogin: userName,
                }
                localStorage.setItem("sessionData", JSON.stringify(sessionData));
                console.log("Stored:" + localStorage.getItem("sessionData"));
                setApiError(null);
                dispatch(sessionRegister(sessionData));

如果Redux中没有存储数据,我的应用程序组件将显示登录表单;如果Redux中存在用户名和令牌,则显示用户名和令牌:

function App(props) {

    const sessionData = useSelector(selectSession);
    const storedSessionData = localStorage.getItem("sessionData");
    
    if (storedSessionData && !sessionData.authToken) {
        console.log("App init check. Storing :");
        console.log(JSON.parse(storedSessionData));
        sessionRegister(JSON.parse(storedSessionData));
    } else {
        if (!storedSessionData) console.log("No sessionData and no stored data");
    }

    return (
        <div className="App">
            <div className="topbar"><Topbar /></div>
            <div className="content">
            {sessionData.authToken ? (
                    <span>User: {sessionData.userLogin} {storedSessionData}</span>
                ) : (
                    <LoginForm />
                )
            }
            </div>
        </div>
    );
}

这一切几乎都奏效了。login组件在API调用后通过Redux存储数据,也存储在localStorage中。应用程序会显示Redux的用户登录名,也会显示localStorage内容。但如果我刷新页面,应用程序将从locaStorage获取数据,但不会调用sessionRegister(或不执行任何操作)。

情况如下:

翻开书页。控制台:无会话数据和无存储数据
通过loginform登录。控制台:

Localy stored:{"authToken":"5467c25e000df49a1161c4ff8ga1f610053f62b8","userLogin":"testuser"} 
Storing in Redux:
Object { authToken: "5467c25e000df49a1161c4ff8ga1f610053f62b8", userLogin: "testuser" }

现在App组件正确地呈现内容而不是登录表单:

User: testuser {"authToken":"5467c25e000df49a1161c4ff8ga1f610053f62b8","userLogin":"testuser"}

到目前为止还不错。但如果我刷新该页面,登录表单将再次显示。在控制台中我得到:

App init check. Storing : App.js:15
Object { authToken: "5467c25e000df49a1161c4ff8ga1f610053f62b8", userLogin: "testuser" } App.js:16
App init check. Storing : App.js:15
Object { authToken: "5467c25e000df49a1161c4ff8ga1f610053f62b8", userLogin: "testuser" } App.js:16

我不明白为什么sessionregister(json.parse(storedSessionData));没有正确执行,为什么我得到两倍的控制台日志app init check

感谢阅读了所有这些,任何帮助将是感激的。

共有1个答案

易修洁
2023-03-14

我想你错过了一个调度

而不是

sessionRegister(JSON.parse(storedSessionData));

应该是

dispatch(sessionRegister(JSON.parse(storedSessionData)));

在应用程序组件中。您可以使用钩子访问dispatch

const dispatch = useDispatch()

最后,但并非最不重要的是,您在每次呈现中都要更新存储,所以这就是为什么您会两次看到日志的原因。我想你应该把这件事

const dispatch = useDispatch()
const sessionData = useSelector(selectSession);
useEffect(() => {
  const storedSessionData = localStorage.getItem("sessionData");
  if (storedSessionData && !sessionData.authToken) {
      console.log("App init check. Storing :");
      console.log(JSON.parse(storedSessionData));
      sessionRegister(JSON.parse(storedSessionData));
  } else {
      if (!storedSessionData) console.log("No sessionData and no stored data");
  }
}, [dispatch, sessionData])
 类似资料:
  • 我有一个C++实验室,问题是:用户应该为X输入一个值(X是所持有的测试数)。如果x<15,程序不计算任何东西。如果X在16和30之间,程序应计算C=1.0/10.0*(24a);如果X>30,程序应计算C=0.15(24*a)。我的multiple if代码可以工作,但是当我输入X的值时,方程没有解出。有人知道吗??

  • 问题内容: 我有一个想法,可能是因为我正在做一些样式设计来更改单选按钮,但是我不确定。我正在设置一个onClick事件,该事件两次调用了我的函数。我已删除它以确保它没有在其他地方被触发,并且onClick似乎是罪魁祸首。 我的功能目前仅是运输选项的简单控制台日志: 如果没有任何理由可以在这里看到为什么会发生这种情况,我可以发布其余代码,但是有很多方面,我认为这与之无关,但是我认为这是一个很好的起点

  • 我尝试了一切,但图像不会显示出来,我试图使图像变小但没有用,我试图改变路径,我试图改变图像的位置但没有帮助,我试图在互联网上搜索但一无所获。 我看到的只是空白的图形用户界面,没有文本和图像。如果你能帮我,你会帮我一个大忙。 代码如下:

  • 我使用surefire和failsafe分别执行单元测试和集成测试。所有测试都位于文件夹中。到目前为止,我有一个集成测试类,其测试方法(用@test注释)在所有单元测试运行时从不执行。这是我的pom的摘录。xml: 我使用maven目标来运行测试。

  • 我正在尝试将一个梅文Spring靴(2.3.12)应用程序从JUnit4转换为JUnit5。我已经阅读了很多关于如何做到这一点的不同帖子。 我能够在Eclipse中执行我的JUnit5测试。 我的问题是我无法让Maven Surefire执行我的JUnit5测试。我尝试了各种配置变体。当它到达Surefire步骤时,它只执行我以前的JUnit4测试,并且简单地忽略任何JUnit5测试。我已经验证了

  • 首先,我看了这里所有其他类似的帖子,但没有一个能帮上忙。我正在写一个扫雷游戏,我试图在JFrame的边界布局顶部放置一个Jlabel,并让它显示一个计数器,指示还有多少地雷需要标记。每当单击网格上的任何其他JLabel时,都需要重新绘制它。首先,对于我的代码,我的标题JLabel上从来没有显示任何文本。让文本显示的唯一方法是将其放入我的JLabel构造函数中。这让我觉得我的paintCompone