diff --git a/src/App.js b/src/App.js
index e02f818..e037c55 100644
--- a/src/App.js
+++ b/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
Hello World!
;
+ const user = useUser();
+
+ return ;
}
export default App;
diff --git a/src/AuthenticatedApp.js b/src/AuthenticatedApp.js
new file mode 100644
index 0000000..7e2a874
--- /dev/null
+++ b/src/AuthenticatedApp.js
@@ -0,0 +1,15 @@
+import { useAuthState } from './context/auth';
+
+function AuthenticatedApp() {
+ const { logout, isPending } = useAuthState();
+
+ return (
+
+
You're logged in!
+
+ {isPending && Loading...
}
+
+ );
+}
+
+export default AuthenticatedApp;
diff --git a/src/UnauthenticatedApp.js b/src/UnauthenticatedApp.js
new file mode 100644
index 0000000..2bfab1c
--- /dev/null
+++ b/src/UnauthenticatedApp.js
@@ -0,0 +1,15 @@
+import { useAuthState } from './context/auth';
+
+function UnauthenticatedApp() {
+ const { login, isPending } = useAuthState();
+
+ return (
+
+
Please, log in!
+
+ {isPending && Loading...
}
+
+ );
+}
+
+export default UnauthenticatedApp;
diff --git a/src/context/auth.js b/src/context/auth.js
new file mode 100644
index 0000000..61f1287
--- /dev/null
+++ b/src/context/auth.js
@@ -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 (
+
+
Something went wrong!
+
{state.error.message ?? 'Unhandled error!'}
+
+ );
+ }
+
+ 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 ;
+}
+
+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 };
diff --git a/src/context/index.js b/src/context/index.js
new file mode 100644
index 0000000..f5ad165
--- /dev/null
+++ b/src/context/index.js
@@ -0,0 +1,12 @@
+import { AuthProvider } from './auth';
+import { UserProvider } from './user';
+
+function AppProviders({ children }) {
+ return (
+
+ {children}
+
+ );
+}
+
+export default AppProviders;
diff --git a/src/context/user.js b/src/context/user.js
new file mode 100644
index 0000000..a4139dc
--- /dev/null
+++ b/src/context/user.js
@@ -0,0 +1,14 @@
+import { createContext, useContext } from 'react';
+import { useAuthState } from './auth';
+
+const UserContext = createContext();
+
+function UserProvider(props) {
+ return ;
+}
+
+function useUser() {
+ return useContext(UserContext);
+}
+
+export { UserProvider, useUser };
diff --git a/src/index.js b/src/index.js
index d563c0f..fa6639d 100644
--- a/src/index.js
+++ b/src/index.js
@@ -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(
-
+
+
+
);