Para realizar o projeto, atente-se a cada passo descrito a seguir.
Aqui você vai encontrar os detalhes de como estruturar o desenvolvimento do seu projeto a partir deste repositório, utilizando uma branch específica para colocar seus códigos. Para fins didáticos, a resolução completa está na branch gabarito
.
👨💻 O que deverá ser desenvolvido
Neste projeto você vai revisar a configuração do Redux a partir de uma aplicação que loga uma pessoa usuária e exibe uma lista de personagens. Ao utilizar essa aplicação um usuário deverá ser capaz de:
- Fazer login na aplicação;
- Visualizar uma lista de personagens;
- Realizar uma busca pelo nome ou alias dos personagens;
📝 Habilidades
Neste projeto, verificamos se você é capaz de:
-
Criar um store Redux em aplicações React
-
Criar reducers no Redux em aplicações React
-
Criar actions no Redux em aplicações React
-
Criar dispatchers no Redux em aplicações React
-
Conectar Redux aos componentes React
-
Criar actions assíncronas na sua aplicação React que faz uso de Redux.
‼️ Antes de começar a desenvolver
- Crie um fork deste repositório
- Crie um fork deste projeto e para isso siga esse tutorial de como realizar um fork.
- Clone o repositório
- Use o comando:
git clone
para clonar o repositório após o fork. - Entre na pasta do repositório que você acabou de clonar:
cd revisao-redux-xmen
- Instale as dependências
npm install
.
- Crie uma branch a partir da branch
main
- Verifique que você está na branch
main
- Exemplo:
git branch
- Exemplo:
- Se não estiver, mude para a branch
main
- Exemplo:
git checkout main
- Exemplo:
- Agora crie uma branch à qual você vai submeter os
commits
do seu projeto- Você deve criar uma branch no seguinte formato:
nome-de-usuario-nome-do-projeto
- Exemplo:
git checkout -b joaozinho-revisao-redux-xmen
- Você deve criar uma branch no seguinte formato:
⌨️ Durante o desenvolvimento
-
Faça
commits
das alterações que você fizer no código regularmente -
Lembre-se de sempre após um (ou alguns)
commits
atualizar o repositório remoto -
Os comandos que você utilizará com mais frequência são:
git status
(para verificar o que está em vermelho - fora do stage - e o que está em verde - no stage)git add
(para adicionar arquivos ao stage do Git)git commit
(para criar um commit com os arquivos que estão no stage do Git)git push -u origin nome-da-branch
(para enviar o commit para o repositório remoto na primeira vez que fizer opush
de uma nova branch)git push
(para enviar o commit para o repositório remoto após o passo anterior)
🛠 Desenvolvimento
Neste projeto você vai configurar o Redux React em uma aplicação já existente. Na implementação você deverá utilizar o seguinte formato do estado global:
{
loginReducer: {
username: ''
},
charactersReducer: {
characters: [],
loading: true,
error: '',
}
}
💡 Configurando o Redux DevTools
Para usarmos o Redux DevTools com o Redux-Thunk, vamos utilizar uma biblioteca chamada redux-devtools-extension
que possui a função composeWithDevTools
. Ela já está no package.json, a única coisa que você vai precisar fazer é configurar a sua store, por exemplo:
import { legacy_createStore as createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from '@redux-devtools/extension';
import thunk from 'redux-thunk';
import rootReducer from './reducers';
const store = createStore(
rootReducer,
composeWithDevTools(
applyMiddleware(thunk),
),
);
export default store;
💡 Consumo da API
Sua página web irá consumir os dados da API gratuita X-Men API Heroku para realizar a busca dos personagens. Já existe um arquivo em src/redux/services/api.js
que traz os resultados necessários. Para realizar essas buscas, o seguinte endpoint é utilizado:
O retorno desse endpoint será algo no formato:
{
"results": [
{
"id": 1,
"name": "Scott Summers",
"alias": "Cyclops",
"description": "He is one of the founding members of the X-Men.",
"powers": [
"Eye Energy Beams"
],
"img": "https://cdn.glitch.com/6137de19-12c5-43e0-9704-2252d809dcfb%2FCyclops.png",
"affiliation": "X-Men",
"created": "2020-12-26T19:48:26.027Z"
},
...
],
"info": {
"count": 23,
"limit": 20,
"pageCount": 2,
"page": 1,
"prev": null,
"next": "https://xmenapiheroku.herokuapp.com/api/characters?page=2"
}
}
Crie uma estrutura de pastas para configurar o Redux. A estrutura pode ser semelhante ao seguinte exemplo:
Estrutura de pastas
revisao-redux-xmen
│
└───src
│
└───redux
│
└───actions
│ │ charactersActions.js
│ │ loginActions.js
│
└───reducers
│ │ index.js
│ │ loginReducer.js
│ │ charactersReducer.js
│
└───store
│ index.js
-
A sua store deve ser criada no arquivo
src/redux/store/index.js
; -
Disponibilize a sua store para a aplicação com um provider;
-
Você deve criar uma store da seguinte forma:
- A extensão
composeWithDevTools
pode ser importada deredux-devtools-extension
; - A função
createStore
oulegacy_createStore
pode ser importada deredux
; - O
applyMiddleware
pode ser importado deredux
, junto com a funçãocreateStore
; - O
thunk
pode ser importado deredux-thunk
; - O rootReducer ainda não existe, mas você já pode deixar importado da pasta
../reducers
; - A
store
deve ser exportada comodefault
.
- A extensão
-
O seu reducer para login deve ser criado no arquivo
src/redux/reducers/loginReducer.js
; -
Você deve criar o reducer da seguinte forma:
- O estado inicial do reducer deve ser no seguinte formato:
{ username: '', }
- O reducer deve ser capaz de salvar o
username
no estado global através de uma action; - O
loginReducer
deve ser exportado comodefault
.
-
O seu reducer para personagens deve ser criado no arquivo
src/redux/reducers/charactersReducer.js
; -
Você deve criar o reducer da seguinte forma:
- O estado inicial do reducer deve ser no seguinte formato:
{ characters: [], loading: true, error: '', }
- Caso requisitado, o reducer deve ser capaz de alterar o
loading
paratrue
no estado global através de uma action; - Caso requisitado, o reducer deve ser capaz de salvar os personagens requisitados em
characters
no estado global através de uma action e retornar oloading
parafalse
; - Caso a requisição falhe, o reducer deve ser capaz de salvar uma mensagem de erro em
error
no estado global através de uma action; - O
charactersReducer
deve ser exportado comodefault
.
-
O seu combineReducers deve ser criado no arquivo
src/redux/reducers/index.js
; -
Você deve criar o combineReducers da seguinte forma:
- A função
combineReducers
pode ser importada deredux
; - O
combineReducers
deve combinar os reducersloginReducer
echaractersReducer
; - O reducer combinado deve ser exportado como
default
.
- A função
-
A sua action para login deve ser criada no arquivo
src/redux/actions/loginActions.js
; -
💡 Dica: você pode colocar o type da sua action em uma constante e exportá-la;
-
Você deve criar a action da seguinte forma:
- A action deve receber um payload;
- A action deve possuir o type
'LOG_IN'
; - A action deve encaminhar o payload;
- A action deve ser exportada como
default
.
-
O seu componente
LoginForm
deve ser capaz de salvar as informações de usuário no estado global; -
Você deve conectar o componente ao estado global da seguinte forma:
- Você deve importar o
connect
dereact-redux
; - O componente fará uma operação de escrita no estado. Para isso, você pode usar o
mapDispatchToProps
; - 💡 Dica: O
mapDispatchToProps
é o segundo parâmetro doconnect
; - 💡 Dica: O
mapDispatchToProps
é uma função que recebedispatch
e retorna um objeto que será mapeado paraprops
; - Já existe uma função
handleClick
no componente. Você deve utilizá-la para dar um dispatch na action desejada; - A action deve ser exportada como
default
.
- Você deve importar o
-
O seu componente
UserInfo
deve ser capaz de ler as informações de usuário do estado global; -
Você deve conectar o componente ao estado global da seguinte forma:
- Você deve importar o
connect
dereact-redux
; - O componente fará uma operação de leitura no estado. Para isso, você deve usar o
mapStateToProps
; - 💡 Dica: O
mapStateToProps
é o primeiro parâmetro doconnect
; - 💡 Dica: O
mapStateToProps
é uma função que recebe o estado global e retorna um objeto que será mapeado paraprops
; - O componente deverá receber como
props
a chaveusername
do reducer de login.
- Você deve importar o
-
As suas actions para personagens devem ser criadas no arquivo
src/redux/actions/charactersActions.js
; -
💡 Dica: você pode colocar o type das suas actions em constantes e exportá-las;
-
Você deve criar a action de requisição da seguinte forma:
- A action não precisa de um payload;
- A action deve possuir o type
'REQUEST_CHARACTERS'
; - 💡 Dica: Esta action apenas vai setar o loading do estado global para
true
.
-
Você deve criar a action de salvar os personagens da seguinte forma:
- A action deve receber um payload;
- A action deve possuir o type
'SAVE_CHARACTERS'
; - A action deve encaminhar o payload;
- 💡 Dica: Esta action vai receber os dados do fetch e salva-los no estado global.
-
Você deve criar a action de erro da seguinte forma:
- A action deve receber um payload;
- A action deve possuir o type
'FAILED_REQUEST'
; - A action deve encaminhar o payload;
- 💡 Dica: Esta action vai receber uma mensagem de erro, caso exista e seja disparada pelo thunk, e salvá-la no estado global.
-
Você deve criar a action thunk da seguinte forma:
- A action deve ser um thunk;
- 💡 Dica: Um thunk é uma action que recebe
dispatch
e retorna uma função assíncrona; - O thunk deve disparar a action
'REQUEST_CHARACTERS'
; - O thunk deve tentar fazer uma requisição assíncrona. A função
fetchCharacters()
deve ser chamada nesta requisição; - Após a requisição, o thunk deve disparar a action
'SAVE_CHARACTERS'
, encaminhando nela o payload com os dados obtidos; - Caso a tentativa da requisição falhe, o thunk deve capturar o erro e disparar a action
'FAILED_REQUEST'
, encaminhando nela o payload com o erro obtido; - O thunk deve ser exportado como
default
.
-
O seu componente
XMenPage
deve ser capaz de salvar as informações de usuário no estado global; -
Você deve conectar o componente ao estado global da seguinte forma:
- Você deve importar o
connect
dereact-redux
; - O componente fará uma operação de escrita no estado. Para isso, você pode usar o
mapDispatchToProps
; - 💡 Dica: O
mapDispatchToProps
é o segundo parâmetro doconnect
; - 💡 Dica: O
mapDispatchToProps
é uma função que recebedispatch
e retorna um objeto que será mapeado paraprops
; - Ao carregar a página, o componente vai disparar o thunk que fará a requisição para a API.
- Você deve importar o
-
O seu componente
PageContent
deve ser capaz de ler as informações de usuário do estado global; -
Você deve conectar o componente ao estado global da seguinte forma:
- Você deve importar o
connect
dereact-redux
; - O componente fará uma operação de leitura no estado. Para isso, você deve usar o
mapStateToProps
; - 💡 Dica: O
mapStateToProps
é o primeiro parâmetro doconnect
; - 💡 Dica: O
mapStateToProps
é uma função que recebe o estado global e retorna um objeto que será mapeado paraprops
; - O componente deverá receber como
props
as três chaves do reducer de personagens:characters
,loading
eerror
; - O componente deverá renderizar os cards de personagens de acordo com o que receber em
characters
.
- Você deve importar o