// contexts/auth-context.js import React, { useReducer, useContext, createContext } from 'react' export const AuthStateContext = createContext() export const AuthDispatchContext = createContext() export const AuthProvider = ({ initialState, reducer, children }) => { const [state, dispatch] = useReducer(reducer, initialState) return ( {children} ) } export const useAuthState = () => { const state = useContext(AuthStateContext) if (state === undefined) { throw new Error(`useAuthState must be within a AuthProvider`) } return state; } export const useAuthDispatch = () => { const dispatch = useContext(AuthDispatchContext) if (dispatch === undefined) { throw new Error(`useAuthDispatch must be used within an AuthProvider`) } return dispatch; } // reducers/auth-reducer.js export const authInitialState = { user: null, loading: false, error: '', } export const authReducer = (state, action) => { switch(action.type) { case 'RESET_STATE': { return authInitialState; } case 'LOGIN': { return { ...state, loading: true } } case 'LOGIN.DONE': { return { ...state, loading: false, user: action.payload } } case 'LOGIN.FAIL': { return { ...state, loading: false, error: action.payload } } case 'LOGOUT': { return { ...state, loading: true } } case 'LOGOUT.DONE': { return { ...state, loading: false, user: null } } case 'LOGOUT.FAIL': { return { ...state, loading: false, error: action.payload } } default: { throw new Error(`The ${action.type} doesn't exists.`) } } } // actions/auth-actions.js // Pollyfill for fetch suggested: unfetch // How to use: import fetch from 'unfetch' export const login = (dispatch) => async (user, password) => { try { dispatch({ type: 'LOGIN' }) const response = fetch(`http://awesome.api/user/login/`, { body: JSON.stringify({ user, password }), headers: { 'Content-Type': 'application/json' }, }) const user = response.json() dispatch({ type: 'LOGIN.DONE', payload: user }) } catch(e) { console.error(`: ${e.message}`) dispatch({ type: 'LOGIN.FAIL', payload: e.message }) } } export const logout = (dispatch) => async () => { try { dispatch({ type: 'LOGOUT' }) const response = fetch(`http://awesome.api/user/logout`) dispatch({ type: 'LOGOUT.DONE' }) } catch(e) { console.error(`: ${e.message}`) dispatch({ type: 'LOGOUT.FAIL', payload: e.message }) } } // index.js import React from 'react' import { AuthProvider } from 'contexts/auth-context' import { authInitialState, authReducer } from 'reducers/auth-reducer' import { App } from 'App' ReactDOM.render( , document.getElementById("root") ); // components/AuthenticatedApp import React from 'react' import { useAuthState, useAuthDispatch } from 'components/auth-context' import { logout } from 'actions/auth-actions' export const AuthenticatedApp = () => { const authState = useAuthState() const authDispatch = useAuthDispatch() return (

{authState.user.name}

) } // components/UnAuthenticatedApp import React, { useState } from 'react' import { useAuthDispatch } from 'components/auth-context' import { login } from 'actions/auth-actions' export const UnAuthenticatedApp = () => { const [user, setUser] = useState('') const [password, setPassword] = useState('') const authDispatch = useAuthDispatch() return (
setUser(e.target.value)} placeholder="Insert you username" /> setPassword(e.target.value)} placeholder="Insert your password" />
) } // App.js import React, {} from 'react' import { AuthenticatedApp } from 'components/AuthenticatedApp' import { UnAuthenticatedApp } from 'components/UnAuthenticatedApp' import { useAuthState } from 'contexts/auth-context.js' export const App = () => { const authState = useAuthState() return authState.user ? : }