I'm trying to develop a React/Redux application for learning purposes and I'm wondering if what I've done so far is a good practice or is not recommended. The first thing that I had to deal with was handle the authorized requests. I have a restfull api Rails back end. This server respond to the login request appending in the headers parameters such as access-token. This access-token is valid just for the next request, that in turn, return a new token valid for the next one and so on.
I implemented this flow in this way: The store dispatch the action that perform the login request passing username and password. Then when the response is ready I store the credentials in the redux store. When I need to perform an authorized request I set those parameters in the header request. When I receive the response I update the credentials in the store with the new ones that I get from the response.
Here my code for more clearity:
import { combineReducers } from 'redux'
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
const initialState = {
currentUser: {
credentials: {},
user: {}
},
test: {},
users: []
}
export const SUBMIT_LOGIN = 'SUBMIT_LOGIN'
export const SET_USER = 'SET_USER'
export const TEST = 'TEST'
export const SET_USERS = 'SET_USERS'
export const SET_CREDENTIALS = 'SET_CREDENTIALS'
//actions
const submitLogin = () => (dispatch) => {
return postLoginRequest()
.then(response => {
dispatch(setCredentials(
response.headers.get('access-token'),
response.headers.get('client'),
response.headers.get('expiry'),
response.headers.get('token-type'),
response.headers.get('uid')
));
return response
})
.then(response => {
return response.json();
})
.then(
(user) => dispatch(setUser(user.data)),
);
}
const performRequest = (api) => (dispatch) => {
return api()
.then(response => {
dispatch(setCredentials(
response.headers.get('access-token'),
response.headers.get('client'),
response.headers.get('expiry'),
response.headers.get('token-type'),
response.headers.get('uid')
));
return response
})
.then(response => {return response.json()})
.then(json => {console.log(json)})
}
const setUsers = (users) => {
return {
type: SET_USERS,
users
}
}
const setUser = (user) => {
return {
type: SET_USER,
user
}
}
const setCredentials = (
access_token,
client,
expiry,
token_type,
uid
) => {
return {
type: SET_CREDENTIALS,
credentials: {
'access-token': access_token,
client,
expiry,
'token-type': token_type,
uid
}
}
}
const currentUserInitialState = {
credentials: {},
user: {}
}
const currentUser = (state = currentUserInitialState, action) => {
switch (action.type) {
case SET_USER:
return Object.assign({}, state, {user: action.user})
case SET_CREDENTIALS:
return Object.assign({}, state, {credentials: action.credentials})
default:
return state
}
}
const rootReducer = combineReducers({
currentUser,
test
})
const getAuthorizedHeader = (store) => {
const credentials = store.getState().currentUser.credentials
const headers = new Headers(credentials)
return headers
}
//store creation
const createStoreWithMiddleware = applyMiddleware(
thunk
)(createStore);
const store = createStoreWithMiddleware(rootReducer);
const postLoginRequest = () => {
return fetch('http://localhost:3000/auth/sign_in', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
email: 'test@test.com',
password: 'password',
})
})
}
const getUsers = () => {
const autorizedHeader = getAuthorizedHeader(store)
debugger
return fetch('http://localhost:3000/users',
{
method: 'GET',
headers : autorizedHeader
}
)
}
store.dispatch(submitLogin())
setTimeout(() => {
console.log(store.dispatch(performRequest(getUsers)))
}, 2000)
I'm wondering if store sensible data in the store in a good practice and if not I'm open to any suggestions to develop this workflow in a better way.
I have also this parameter on my server
config.batch_request_buffer_throttle = 5.seconds
Sometimes it's necessary to make several requests to the API at the same time. In this case, each request in the batch will need to share the same auth token. This setting determines how far apart the requests can be while still using the same auth token.
In this way I could not dispatch the setCredentials action in my performRequest function if the token is still valid but I don't really have ideas how to check it.
Thanks