유저 기기에 회원 auth 정보를 저장할 수 있는 기능을 커스텀 훅으로 제작한다. 재사용을 위해 따로 디렉토리를 만들어 저장한다.
// useLocalStorage.ts
import { useState } from 'react';
import AsyncStorage from '@react-native-async-storage/async-storage';
export const useLocalStorage = () => {
const [value, setValue] = useState<string | null>(null);
const setItem = (key: string, value: string) => {
localStorage.setItem(key, value);
setValue(value);
};
const getItem = (key: string) => {
const value = localStorage.getItem(key);
setValue(value);
return value;
};
const removeItem = (key: string) => {
localStorage.removeItem(key);
setValue(null);
};
return { value, setItem, getItem, removeItem };
};
회원 auth 정보를 context와 localStorage에 저장하는 커스텀 훅을 만든다.
// useUser.ts
import { useContext } from 'react';
import { AuthContext } from '../context/AuthContext';
import { useLocalStorage } from './useLocalStorage';
export interface User {
id: string;
name: string;
email: string;
authToken?: string;
}
export const useUser = () => {
const { user, setUser } = useContext(AuthContext);
const { setItem } = useLocalStorage();
const addUser = (user: User) => {
setUser(user);
setItem('user', JSON.stringify(user));
};
const removeUser = () => {
setUser(null);
setItem('user', '');
};
return { user, login, logout };
};
위에 두가지 훅을 사용할 때다. 또 하나의 훅을 만들어 로그인과 로그아웃 함수까지 추가해본다.
// useAuth.ts
import { useEffect } from 'react';
import { useUser } from './useUser';
import { useLocalStorage } from './useLocalStorage';
export const useAuth = () => {
const { user, addUser, removeUser } = useUser();
const { getItem } = useLocalStorage();
useEffect(() => {
const user = getItem('user');
if (user) {
addUser(JSON.parse(user));
}
}, []);
const login = (user: User) => {
addUser(user);
};
const logout = () => {
removeUser();
};
return { user, login, logout };
};
// AuthContext.ts
import { createContext } from 'react';
import { User } from '../hooks/useUser';
interface AuthContext {
user: User | null;
setUser: (user: User | null) => void;
}
export const AuthContext = createContext<AuthContext>({
user: null,
setUser: () => {},
});
최상단 (주로 App.tsx) 파일에 가서 context provider로 app을 감싼다.
// App.tsx
import { AuthContext } from './context/AuthContext';
import { useAuth } from './hooks/useAuth';
const App = () => {
const { user, login, logout } = useAuth();
return (
<AuthContext.Provider value={{ user, setUser }}>
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</div>
</AuthContext.Provider>
);
};
export default App;
import { useAuth } from '../hooks/useAuth';
const Login = () => {
const { login } = useAuth();
const handleLogin = () => {
login({
id: '1',
name: 'John Doe',
email: 'john.doe@email.com',
});
};
return (
<div>
<h1>Login</h1>
<button onClick={handleLogin}>Login</button>
</div>
);
};
export default Login;
import { useAuth } from '../hooks/useAuth';
const LogoutButton = () => {
const { logout } = useAuth();
return <button onClick={logout}>Logout</button>;
};
export default LogoutButton;