From fd6e663a1bcc43cfc49bda99ccbfab380489324b Mon Sep 17 00:00:00 2001 From: eug-vs Date: Mon, 10 Aug 2020 00:02:24 +0300 Subject: feat!: add useLocalStorage hook --- src/hooks/APIClient.ts | 6 ++-- src/hooks/useAuth.tsx | 65 ++++++++++++++++++++------------------------ src/hooks/useLocalStorage.ts | 16 +++++++++++ 3 files changed, 48 insertions(+), 39 deletions(-) create mode 100644 src/hooks/useLocalStorage.ts (limited to 'src/hooks') diff --git a/src/hooks/APIClient.ts b/src/hooks/APIClient.ts index ce11134..7f7d170 100644 --- a/src/hooks/APIClient.ts +++ b/src/hooks/APIClient.ts @@ -9,9 +9,9 @@ const arrayOptions = { revalidateOnMount: true }; -export const useUser = (username: string) => { +export const useUser = (username: string | null) => { return useSWR( - `/users?username=${username}`, + username && `/users?username=${username}`, (url: string) => get(url).then(response => response.data[0]) ); }; @@ -21,5 +21,5 @@ export const useProfile = (id: string) => { }; export const useFeed = () => { - return useSWR(`/feed`, fetcher, arrayOptions); + return useSWR('/feed', fetcher, arrayOptions); }; diff --git a/src/hooks/useAuth.tsx b/src/hooks/useAuth.tsx index 55e142c..ed1e428 100644 --- a/src/hooks/useAuth.tsx +++ b/src/hooks/useAuth.tsx @@ -1,67 +1,60 @@ import React, { - useState, useEffect, useContext, createContext + useEffect, useCallback, useMemo, useContext, createContext } from 'react'; import { User } from 'which-types'; -import { post, get } from '../requests'; +import { post } from '../requests'; +import { useUser } from './APIClient'; +import useLocalStorage from './useLocalStorage'; interface ContextType { user: User | null, - setUser: (user: User) => void; login: (username: string, password: string, remember?: boolean) => Promise; logout: () => void; - isAuthenticated: () => boolean; + isAuthenticated: boolean; } const authContext = createContext({ user: null, - setUser: () => {}, login: async () => false, logout: () => {}, - isAuthenticated: () => false + isAuthenticated: false }); const useProvideAuth = () => { - const [user, setUser] = useState(null); + const [remember, setRemember] = useLocalStorage('remember'); + const [username, setUsername] = useLocalStorage('username'); + const [token, setToken] = useLocalStorage('token'); + const { data: user } = useUser(username); - const login: ContextType['login'] = (username, password, remember = true) => { + const isAuthenticated = useMemo(() => Boolean(username), [username]); + + const logout = useCallback(() => { + setToken(null); + setUsername(null); + }, [setToken, setUsername]); + + useEffect(() => { + // If should not remember, logout + if (!remember) logout(); + }, [remember, logout]); + + + const login: ContextType['login'] = (name, password, shouldRemember = true) => { return post('/authentication', { strategy: 'local', - username, + username: name, password }).then(response => { - const me = response.data.user; - const token = response.data.accessToken; - setUser(me); - localStorage.setItem('userId', me._id); - localStorage.setItem('token', token); - if (!remember) localStorage.setItem('shouldClear', 'true'); + setToken(response.data.accessToken); + setUsername(name); + setRemember(shouldRemember ? 'true' : null); return true; }).catch(() => false); }; - const logout = () => { - setUser(null); - localStorage.removeItem('userId'); - localStorage.removeItem('token'); - }; - - const isAuthenticated = () => Boolean(user); - - useEffect(() => { - if (localStorage.getItem('shouldClear')) { - localStorage.clear(); - } - const userId = localStorage.getItem('userId'); - if (userId) { - get(`/users/${userId}`).then(response => { - setUser(response.data); - }); - } - }, []); - return { - user, setUser, login, logout, isAuthenticated + user, login, logout, token, isAuthenticated }; }; diff --git a/src/hooks/useLocalStorage.ts b/src/hooks/useLocalStorage.ts new file mode 100644 index 0000000..faf1411 --- /dev/null +++ b/src/hooks/useLocalStorage.ts @@ -0,0 +1,16 @@ +import { useState, useCallback } from 'react'; + +type Value = string | null; +type Setter = (value: Value) => void; + +export default (key: string): [Value, Setter] => { + const [state, setState] = useState(() => localStorage.getItem(key) || null); + + const update: Setter = useCallback(value => { + if (value) localStorage.setItem(key, value); + else localStorage.removeItem(key); + setState(value); + }, [key]); + + return [state, update]; +}; -- cgit v1.2.3