从 redux 内部 props 访问状态更改,状态成功更改但该对象的 props 未定义

时间:2021-03-23 13:02:53

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

这里是第一位提问者!

我是 React 的新手,发现使用 redux 管理状态很混乱。从 redux-logger 输出来看,我似乎成功地更改了有关用户登录的 redux 状态,但我真的不知道如何将其设置为 props,因此,我得到了 currentUser 的未定义值(这是我想在所有页面上管理的道具)。我同时使用 withRouter 和 Redux 以将用户属性传递给 app.js。

首先调用后端的 API 来查看用户是否可以登录,如果成功则返回一个对象 {isAdmin: "", uId: ""}。


import React from "react";
import { withRouter } from "react-router-dom";
import { setCurrentUser } from "../../redux/user/user-actions";
import { connect } from "react-redux";

// sign-in.jsx
class Login extends React.Component {
  constructor(props) {
    super(props);
}

onSubmitClick = async (e) => {
    e.preventDefault();

    fetch("/api/login", {
      method: "post",
      body: JSON.stringify({
        email: "",
        password: "",
      }),
    })
      .then((res) => res.json())
      .then((user) => {
        if (user.error) {
          this.setState({ error: user.error });
        } else {
          // Set the user in redux too:
          this.props.dispatch(setCurrentUser(user));
          // Redirect to main page after login
          this.props.history.push({
            pathname: "/",
            search: "?uid=" + user.key + "?admin=" + user.admin,
            state: { userId: user.key, isAdmin: user.admin },
          });
        }
      });
};

render() {
    return (...)
}

const mapStateToProps = ({ user }) => ({
  currentUser: user.currentUser,
});

export default connect(mapStateToProps)(withRouter(Login));

代码行:this.props.dispatch(setCurrentUser(user)); 成功更改了状态,但未更改 props 值。

这里是 redux 的东西:

// user-actions.js --------------------------------------------------------------------------------------

export const setCurrentUser = (user) => ({
  type: "SET_CURRENT_USER",
  payload: user,
});


// user-reducer.js --------------------------------------------------------------------------------------

// The initial state is basically a null user (ID)
const initialState = {
  user: null,
};

/*
This is essentially a function that takes the current state
and action as an argument and returns a new state result. 
i.e. (state, action) => newState
*/
const userReducer = (state = initialState, action) => {
  // Conditional for the current action type
  if (action.type.localeCompare("SET_CURRENT_USER") === 0) {
    // Return a new state object
    return {
      // Which has the existing data but also..
      ...state,
      // The new user object (just an ID at this point)
      user: action.payload,
    };
  } else {
    // Otherwise we return the state unchanged
    // (usually when the reducer doesnt pick up the certain action)
    return state;
  }
};

export default userReducer; 


// store.js --------------------------------------------------------------------------------------

import { createStore, applyMiddleware } from "redux";


/*
Useful for debugging redux --> logger 
Is a logger middleware that console.logs the actions fired and change of state
*/
import logger from "redux-logger";

import rootReducer from "./root-reducer";

const middlewares = [logger];

const store = createStore(rootReducer, applyMiddleware(...middlewares));

export default store;

// root-reducer.js --------------------------------------------------------------------------------------

import { combineReducers } from "redux";

import userReducer from "./user/user-reducer";

export default combineReducers({
  user: userReducer,
});

最后是 App.js 相关代码


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      ...props,
      u_id: null,
    };
  }
  unsubscribeFromAuth = null;

  componentDidMount() {
    const { setCurrentUser } = this.props;[enter image description here][1]
    const userState = this.props.location;
    console.log(this.props);
    // Make sure that state for a user isnt undefined
    if (userState.state) {
      this.unsubscribeFromAuth = true;
      const user = userState.state.userId;
      this.props.dispatch(setCurrentUser(user));
    }
    console.log(this.props);
  }

  componentWillUnmount() {
    this.unsubscribeFromAuth = false;
  }

  render() {
     return (...)
  }
}

const mapStateToProps = (state) => ({
  currentUser: state.currentUser,
});

//Access the state and dispatch function from our store
const mapDispatchToProps = (dispatch) => ({
  setCurrentUser: (user) => dispatch(setCurrentUser(user)),
  dispatch,
});

export default connect(mapStateToProps, mapDispatchToProps)(withRouter(App));


使用 redux-logger 的控制台输出:

https://i.stack.imgur.com/r9JyV.png

  • 如您所见,currentUser 未定义,但位置中的所有道具都在那里,在使用 setCurrentUser 操作设置 currentUser 时,我可能犯了一些非常愚蠢的错误,无论是在登录中还是在app.jsx
  • 中的 componentDidMount
  • 我会根据要求添加更多细节

任何帮助将不胜感激! :)

1 个答案:

答案 0 :(得分:0)

您将用户保存在 user 下的 redux 中,但您试图通过 currentUser 在 mapStateToPRops 中访问它:

const mapStateToProps = (state) => ({ currentUser: state.currentUser, });

将其更改为 const mapStateToProps = (state) => ({ currentUser: state.user, });

它应该可以工作。

还有这个:

const mapDispatchToProps = (dispatch) => ({
  setCurrentUser: (user) => dispatch(setCurrentUser(user)),
  dispatch,
});

相当于:

const mapDispatchToProps = ({
 setCurrentUser
});

https://react-redux.js.org/using-react-redux/connect-mapdispatch#defining-mapdispatchtoprops-as-an-object