MERN堆栈:使用Redux存储用户是否已登录

时间:2019-05-29 19:12:47

标签: javascript express redux passport.js state

我是后端编程和构建我的第一个完整堆栈项目的新手,并且是第一次使用Express / Mongoose / Mongo和Passport.js。

我已经建立了“使用Github登录”功能,并设置了Passport。现在,我想使用Redux来存储用户是否登录。如果用户已登录,我想更改导航栏,即如果用户未登录,则一个链接会显示“登录”,但是如果用户登录后,“登录”链接更改为“个人资料”。

我知道我可以在React组件中使用三元运算符来切换链接,具体取决于用户是否已登录。

如何使用Redux来存储用户是否已登录?这是我到目前为止的内容:

Redux动作:

export function loggedIn() {
    return {
      type: "LOGGED_IN",
      loggedIn: false
    }
};

Redux减速器:

export default function reducer(state = {
  loggedIn: false
}, action) {
  switch(action.type) {
    case "LOGGED_IN": {
      return {
        ...state,
        loggedIn: true
      }
    }
    case "LOGGED_OUT": {
      return {
        ...state,
        loggedIn: false
      }
    }
    default: return state;
  }

}

我是我的Express路线,正在使用以下中间件:

// Checks if user is not logged in
const authCheck = (req, res, next) => {
    if(!req.user) {
      // If user is not logged in, redirect them to login page
      res.redirect('/auth/login');
    }
    else {
      // If user is logged in call next in router.get

      // Would this be the proper place to dispatch to the Redux store 
      // whether a user is logged in?
      dispatch(loggedIn(true));
      // After updating the Redux store call next()
      next();
    }
};

如何正确存储用户是否已登录/注销的状态,然后在React组件中访问此状态,以便我可以使用三元运算符选择在导航中显示“已登录”还是“配置文件”酒吧吗?

2 个答案:

答案 0 :(得分:1)

建议不要将后端路由与reducer调度混合使用。我建议您在中间件中发送回信res.status(200).send({ loggedIn: true })

// Checks if user is not logged in
const authCheck = (req, res, next) => {
    if(!req.user) {
      // If user is not logged in, redirect them to login page
      res.redirect('/auth/login');
    }
    else {
      res.status(200).send({ loggedIn: true })
      next();
    }
};

对该中间件的调用可以根据响应调度成功。

 if (res.status === 200) {
  dispatch(loggedIn(res.loggedIn));
 }
 else {
  dispatch({ type: 'LOGIN_FAILED'})
 }

答案 1 :(得分:0)

您应该只在React前端中处理身份验证状态。即使您正在执行服务器端身份验证,最好还是使用Redux将身份验证状态保存在您的React前端中。在您的React应用中:

您还需要使用react-redux库来连接react和redux

动作

export const login_success = () => {
  return {
    type: ACTION_TYPES.LOGIN_SUCCESS
  }
}

export const login_failure = () => {
  return {
    type: ACTION_TYPES.LOGIN_FAILURE
  }
}

减速器:

const initialState = {
  isAuthenticated: false,

}


const AuthReducer = (state= initialState, action) => {
  switch(action.type) {
    case ACTION_TYPES.LOGIN_SUCCESS:
      return {
        ...state,
        isAuthenticated: true
      }
    case ACTION_TYPES.LOGIN_FAILURE:
      return {
        ...state,
        isAuthenticated: false
      }
}

使用道具访问身份验证状态

 {this.props.isAuthenticated
         ? <h3> user is logged in </h3>
         : <h3> user is not logged in </h3>
       }

function mapStateToProps(state) {
  return {
     isAuthenticated: state.auth_reducer.isAuthenticated
  }
}

在用户登录后呈现的回调组件中实现此功能。

function mapDispatchToProps(dispatch) {
  return {
    action1: () => dispatch(ACTIONS.LOGIN_SUCCESS),
  }
}

如果您想了解如何执行此操作的完整示例,可以查看我构建的该项目,它是具有身份验证功能的全堆栈React Express应用程序

https://github.com/iqbal125/react-redux-fullstack-blog

为了给您一些坚强的爱,在我看来您不完全了解Redux,我建议您在尝试构建复杂的全栈应用程序之前先精通Redux,这只是一个建议。

编辑:

可以通过代理与服务器进行通信,因此可以在react应用的package.json中进行

"proxy": http://localhost:5000"

或您的节点服务器正在运行的任何位置。您也可以将服务器响应(无论任何情况)发送回React前端,然后根据该服务器响应更新React-Redux前端。

所以在您的快递服务器中

router.get('api/login', (req, res) => { 
  if(res.login === true) { 
    res.json(success_login: true)
  }
})

然后在您的反应前端

axios.get('/api/login')
  .then(res => this.props.login_success(res.data) )

login_success(res) {
  if(res.success_login === true) {
    type: "SUCCESS_LOGIN"
} 

因此,从本质上讲,您将不会在快递服务器中处理任何路由或redux身份验证状态。您的服务器将向您的React前端发送响应,然后路由和Redux身份验证状态将由您的前端处理。