Autenticação

Configurações do Redux

Instalações

Dependências iniciais do Redux:

$ yarn add redux redux-saga react-redux reactotron-redux reactotron-redux-saga immer

Arquivo src/store/modules/auth/reducer.js

const INITIAL_STATE = {};
export default function auth(state = INITIAL_STATE, action) {
switch (action.type) {
default:
return state;
}
}

Arquivo src/store/modules/auth/sagas.js

import { all } from 'redux-saga/effects';
export default all([]);

Arquivo src/store/modules/rootReducer.js

import { combineReducers } from 'redux';
import auth from './auth/reducer';
export default combineReducers({ auth });

Arquivo src/store/modules/rootSaga.js

import { all } from 'redux-saga/effects';
import auth from './auth/sagas';
export default function* rootSaga() {
return yield all([auth]);
}

Arquivo src/store/index.js

import createSagaMiddleware from 'redux-saga';
import createStore from './createStore';
import rootReducer from './modules/rootReducer';
import rootSaga from './modules/rootSaga';
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const store = createStore(rootReducer, middlewares);
sagaMiddleware.run(rootSaga);
export default store;

Arquivo src/store/createStore.js

import { createStore } from 'redux';
export default (reducers, middlewares) => {
return createStore(reducers, middlewares);
};

Configurações

Configurações do Reactotron

Arquivo src/config/ReactotronConfig.js*

Configurações do Reactotron

import Reactotron from 'reactotron-react-js';
import { reactotronRedux } from 'reactotron-redux';
import reactotronSaga from 'reactotron-redux-saga';
if (process.env.NODE_ENV === 'development') {
const tron = Reactotron.configure()
.use(reactotronRedux())
.use(reactotronSaga())
.connect();
tron.clear();
console.tron = tron;
}

Arquivo src/store/index.js

Alteração no sagaMiddleware e criação do sagaMonitor:

// ...
const sagaMonitor =
process.env.NODE_ENV === 'development'
? console.tron.createSagaMonitor()
: null;
const sagaMiddleware = createSagaMiddleware({ sagaMonitor });
// ...

Arquivo src/store/createStore.js

Criação da variável enhancer para utilização do Reactotron.

import { createStore, compose, applyMiddleware } from 'redux';
export default (reducers, middlewares) => {
const enhancer =
process.env.NODE_ENV === 'development'
? compose(console.tron.createEnhancer(), applyMiddleware(...middlewares))
: applyMiddleware(...middlewares);
return createStore(reducers, enhancer);
};

Arquivo src/App.js

Inserção do Provider entre todos os componentes e do método store após as configurações do Reactotron:

// import React from 'react';
import { Provider } from 'react-redux';
// import { Router } from 'react-router-dom';
import './config/ReactotronConfig';
// import Routes from './routes';
// import history from './services/history';
import store from './store';
// import GlobalStyle from './styles/global';
function App() {
return (
<Provider store={store}>
{/*
<Router history={history}>
<Routes />
<GlobalStyle />
</Router>
*/}
</Provider>
);
}
export default App;

Autenticação do usuário

Criação das actions de Autenticação

Arquivo src/store/modules/auth/actions.js

export function signInRequest(email, password) {
return {
type: '@auth/SIGN_IN_REQUEST',
payload: { email, password },
};
}
export function signInSuccess(token, user) {
return {
type: '@auth/SIGN_IN_SUCCESS',
payload: { token, user },
};
}
export function signFailure() {
return {
type: '@auth/SIGN_FAILURE',
};
}

Instalar o Axios com o comando $ yarn add axios e criar o arquivo src/services/api.js:

import axios from 'axios';
const api = axios.create({
baseURL: 'http://localhost:3333',
});
export default api;

Implementação da tratativa de login com o Redux Saga

Arquivo src/store/modules/auth/sagas.js

import { takeLatest, call, put, all } from 'redux-saga/effects';
import { signInSuccess } from './actions';
import api from '~/services/api';
import history from '~/services/history';
export function* signIn({ payload }) {
const { email, password } = payload;
const response = yield call(api.post, 'sessions', {
email,
password,
});
const { token, user } = response.data;
if (!user.provider) {
console.tron.error('Usuário não é prestador');
}
yield put(signInSuccess(token, user));
history.push('/dashboard');
}
export default all([takeLatest('@auth/SIGN_IN_REQUEST', signIn)]);

Configurações da tela de Login

Arquivo src/pages/SignIn/index.js

Importação do useDispatch e da Action de SignIn criada anteriormente:

import { useDispatch } from 'react-redux';
import { signInRequest } from '~/store/modules/auth/actions';

Criação da função de login dentro do componente (function SignIn() {...}):

const dispatch = useDispatch();
function handleSubmit({ email, password }) {
dispatch(signInRequest(email, password));
}

Lidando com o token para redirecionar para a aplicação

Arquivo src/store/modules/auth/reducer.js

import produce from 'immer';
const INITIAL_STATE = {
token: null,
signed: false,
loading: false,
};
export default function auth(state = INITIAL_STATE, action) {
switch (action.type) {
case '@auth/SIGN_IN_SUCCESS':
return produce(state, draft => {
draft.token = action.payload.token;
draft.signed = true;
});
default:
return state;
}
}

Alterações no arquivo de rotas

Arquivo src/routes/Route.js

Importação do arquivo store:

import store from '~/store'

Alteração da variável signed:

const { signed } = store.getState().auth;

Armazenando os dados do usuário

Criação dos arquivos referentes ao Redux para o user:

  • src
    • store
      • modules
        • user
          • actions.js
          • reducer.js
          • sagas.js

Arquivo src/store/modules/user/reducer.js

import produce from 'immer';
const INITIAL_STATE = {
profile: null,
};
export default function user(state = INITIAL_STATE, action) {
switch (action.type) {
case '@auth/SIGN_IN_SUCCESS':
return produce(state, draft => {
draft.profile = action.payload.user;
});
default:
return state;
}
}

Arquivo src/store/modules/user/sagas.js

import { all } from 'redux-saga/effects';
export default all([]);

Importar o user no rootSaga e rootReducer