I use JWT token authentication for auth.
When I access to localhost:4000/api/refresh with token, it verify if token is expired, and return refreshed token with status code 200.
And middleware detect if token is valid and return to 200 or 401.
Backend is works perfectly. But frontend got some errors.
I use redux for global state manage.
Here is my codes.
[reducers.js]
// Actions
const LOGIN_TRUE = 'LOGIN_TRUE';
const LOGIN_FALSE = 'LOGIN_FALSE';
const CHECK_TOKEN = 'CHECK_TOKEN';
const REFRESH_TOKEN = 'REFRESH_TOKEN';
// Action Creators
function loginTrue() {
return {
type: LOGIN_TRUE
}
}
function loginFalse() {
return {
type: LOGIN_FALSE
}
}
function checkToken() {
return {
type: CHECK_TOKEN
}
}
function refreshToken() {
return {
type: REFRESH_TOKEN
}
}
// Reducer
const initialState = {
isLogin: false
}
function reducer(state = initialState, action) {
switch(action.type) {
case LOGIN_TRUE:
return applyLoginTrue(state, action);
case LOGIN_FALSE:
return applyLoginFalse(state, action);
case CHECK_TOKEN:
return applyCheckToken(state, action);
case REFRESH_TOKEN:
return applyRefreshToken(state, action);
default:
return state;
}
}
// Reducer Functions
function applyLoginTrue(state) {
return {
...state,
isLogin: true
}
}
function applyLoginFalse(state) {
return {
...state,
isLogin: false
}
}
function applyCheckToken(state) {
const token = localStorage.getItem('token');
if(token !== null) {
return {
...state,
isLogin: true
}
} else {
return {
...state,
isLogin: false
}
}
}
function applyRefreshToken(state) {
console.log(state);
const token = localStorage.getItem('token');
if(token !== null) {
fetch("http://localhost:4000/api/refresh", {
method: "POST",
headers: {
'Authorization':`JWT ${token}`
}
})
.then(res => {
if(res.status === 200) {
return res.json();
} else {
console.log("applyRefreshToken() res.status is not 200");
}
})
.then(json => {
localStorage.clear();
localStorage.setItem('token', json.token);
return {
...state,
isLogin: true
}
})
} else {
console.log("applyRefreshToken() token is null");
return {
...state,
isLogin: false
}
}
}
// Export Action Creators
export const actionCreators = {
loginTrue,
loginFalse,
checkToken,
refreshToken
};
// Export Reducer
export default reducer;
After wrote the reducer.js, I made dummy component to test it.
componentDidMount() {
const { refreshToken } = this.props;
refreshToken();
}
render () {
const { isLogin } = this.props;
return (
<div className="wrap">
{ isLogin ? "Under Construction" : "Login please" }
</div>
)
}
export default connect(mapStateToProps, mapDispatchToProps)(index);
But it throw errors like this -> TypeError: Cannot read property 'isLogin' of undefined
I can't find where is the error occured.
Because loginTrue(), loginFalse(), checkToken() works perfectly.
Is there any solution about this?
Thanks.
[mapStateToProps.js]
const mapStateToProps = (state) => {
const { isLogin } = state;
return {
isLogin
}
}
export default mapStateToProps;
[mapDispatchToProps.js]
import { bindActionCreators } from 'redux';
import { actionCreators } from './reducer';
const mapDispatchToProps = (dispatch) => {
return {
loginTrue: bindActionCreators(actionCreators.loginTrue, dispatch),
loginFalse: bindActionCreators(actionCreators.loginFalse, dispatch),
checkToken: bindActionCreators(actionCreators.checkToken, dispatch),
refreshToken: bindActionCreators(actionCreators.refreshToken, dispatch)
}
}
export default mapDispatchToProps;