Add simple authentication logic
This commit is contained in:
parent
ba06dce15b
commit
5b3465844c
7 changed files with 128 additions and 2 deletions
10
src/App.js
10
src/App.js
|
@ -1,5 +1,13 @@
|
|||
import { lazy } from 'react';
|
||||
import { useUser } from './context/user';
|
||||
|
||||
const AuthenticatedApp = lazy(() => import('./AuthenticatedApp'));
|
||||
const UnauthenticatedApp = lazy(() => import('./UnauthenticatedApp'));
|
||||
|
||||
function App() {
|
||||
return <h1>Hello World!</h1>;
|
||||
const user = useUser();
|
||||
|
||||
return <div>{user ? <AuthenticatedApp /> : <UnauthenticatedApp />}</div>;
|
||||
}
|
||||
|
||||
export default App;
|
||||
|
|
15
src/AuthenticatedApp.js
Normal file
15
src/AuthenticatedApp.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { useAuthState } from './context/auth';
|
||||
|
||||
function AuthenticatedApp() {
|
||||
const { logout, isPending } = useAuthState();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>You're logged in!</h2>
|
||||
<button onClick={logout}>Logout</button>
|
||||
{isPending && <h1>Loading...</h1>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default AuthenticatedApp;
|
15
src/UnauthenticatedApp.js
Normal file
15
src/UnauthenticatedApp.js
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { useAuthState } from './context/auth';
|
||||
|
||||
function UnauthenticatedApp() {
|
||||
const { login, isPending } = useAuthState();
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h2>Please, log in!</h2>
|
||||
<button onClick={login}>Log in</button>
|
||||
{isPending && <h1>Loading...</h1>}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default UnauthenticatedApp;
|
59
src/context/auth.js
Normal file
59
src/context/auth.js
Normal file
|
@ -0,0 +1,59 @@
|
|||
import { createContext, useContext, useState } from 'react';
|
||||
|
||||
const sleep = time => new Promise(resolve => setTimeout(resolve, time));
|
||||
const getUser = () => sleep(1000).then(() => ({ username: 'Leonardo' }));
|
||||
|
||||
const AuthContext = createContext();
|
||||
|
||||
function AuthProvider(props) {
|
||||
const [state, setState] = useState({
|
||||
status: 'idle',
|
||||
user: null,
|
||||
error: null,
|
||||
});
|
||||
|
||||
if (state.status === 'error' && state.error) {
|
||||
return (
|
||||
<div>
|
||||
<h1>Something went wrong!</h1>
|
||||
<pre>{state.error.message ?? 'Unhandled error!'}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
const login = () => {
|
||||
setState({ ...state, status: 'pending' });
|
||||
return getUser().then(user =>
|
||||
setState({ status: 'success', user: user, error: null })
|
||||
);
|
||||
};
|
||||
|
||||
const logout = () => {
|
||||
setState({ ...state, status: 'pending' });
|
||||
return getUser().then(() =>
|
||||
setState({ status: 'success', user: null, error: null })
|
||||
);
|
||||
};
|
||||
|
||||
return <AuthContext.Provider value={{ state, login, logout }} {...props} />;
|
||||
}
|
||||
|
||||
function useAuthState() {
|
||||
const { state, login, logout } = useContext(AuthContext);
|
||||
const isPending = state.status === 'pending';
|
||||
const isError = state.status === 'error';
|
||||
const isSuccess = state.status === 'success';
|
||||
const isAuthenticated = state.user && isSuccess;
|
||||
|
||||
return {
|
||||
user: state.user,
|
||||
isPending,
|
||||
isError,
|
||||
isSuccess,
|
||||
isAuthenticated,
|
||||
login,
|
||||
logout,
|
||||
};
|
||||
}
|
||||
|
||||
export { AuthProvider, useAuthState };
|
12
src/context/index.js
Normal file
12
src/context/index.js
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { AuthProvider } from './auth';
|
||||
import { UserProvider } from './user';
|
||||
|
||||
function AppProviders({ children }) {
|
||||
return (
|
||||
<AuthProvider>
|
||||
<UserProvider>{children}</UserProvider>
|
||||
</AuthProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default AppProviders;
|
14
src/context/user.js
Normal file
14
src/context/user.js
Normal file
|
@ -0,0 +1,14 @@
|
|||
import { createContext, useContext } from 'react';
|
||||
import { useAuthState } from './auth';
|
||||
|
||||
const UserContext = createContext();
|
||||
|
||||
function UserProvider(props) {
|
||||
return <UserContext.Provider value={useAuthState().user} {...props} />;
|
||||
}
|
||||
|
||||
function useUser() {
|
||||
return useContext(UserContext);
|
||||
}
|
||||
|
||||
export { UserProvider, useUser };
|
|
@ -3,11 +3,14 @@ import ReactDOM from 'react-dom/client';
|
|||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
import AppProviders from './context';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<AppProviders>
|
||||
<App />
|
||||
</AppProviders>
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
|
|
Loading…
Reference in a new issue