React context를 사용하면 특정한 데이터를 authContext가 감싼 범위내의 컴포넌트에서도 업데이트 하고 사용 할 수 있다.
내가 이해한대로 그려봤다
본래 부모컴포넌트에서 하나씩 상속 받아야할 데이터를 contextProvider 내의 컴포넌트라면 context에서 받아쓸 수 있다.
여기서 isAuth라는 true일때 로그인상태고 false이면 로그아웃인 state가 있을때 ,
컴포넌트가 컨텍스트에서 isAuth값을 상속해서 어떤 컴포넌트를 가도 로그인 / 아웃 상태를 유지 할 수 있다.
또한 context에서 isAuth의 데이터를 업데이트하여 로그인/아웃 상태를 변경 할 수 있다.
function App() {
return (
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/login" element={<LoginPage />}></Route>
<Route path="/register" element={<RegisterPage />}></Route>
</Routes>
);
}
여기서 Routes안의 모든 컴포넌트안에서 Context를 사용하려한다면
react 내장함수인 createContext를 사용한다.
const AuthContext = createContext();
선언해준다.
import React, { createContext } from 'react';
자동으로 추가된다.
const yourContext = createContext();
const yourValue = "hello world";
const yourFunc = (x, y) => x + y;
<yourContext.Provider value = {yourValue,yourFunc}>
<App/>
</yourContext.Provider>
context의 state값은 Provider로 감싸준 범위안에서 사용가능하다.
yourValue
yourFunc
value에 들어갈 값, App 컴포넌트에서 사용할 데이터, 데이터를 업데이트하는 함수
여기서 <App/>
컴포넌트는 Provider의 범위내에 있기 때문에 Provider의 value값을 언제든지 사용할 수 있다.
function App() {
const AuthContext = createContext();
const yourValue = 'Hello World'
return (
<AuthContext.Provider value={yourValue}>
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/login" element={<LoginPage />}></Route>
<Route path="/register" element={<RegisterPage />}></Route>
</Routes>
</AuthContext.Provider>
);
}
좀더 복잡한 로직을 구현하기 위해서 context도 컴포넌트처럼 폴더를 따로 만들어주고 context마다 파일을 생성한다.
// src/context/AuthContext.js
import { createContext } from "react";
export const AuthContext = createContext;
const AuthContextProvider = ({children}) => {
return (
<AuthContext.Provider value>
{children}
</AuthContext.Provider>
)
}
export default AuthContextProvider;
이런식으로 파일 따로 빼서 프랍에 children을 넣어주고 children요소를 감싸주는 함수를 만든다.
이걸 export default로 빼와서 App.js 에 적용한다
// /src/App.js
import './App.css';
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import LandingPage from './pages/LandingPage/LandingPage';
import LoginPage from './pages/LoginPage/LoginPage';
import RegisterPage from './pages/RegisterPage/RegisterPage';
import AuthContextProvider from './context/AuthContext';
function App() {
return (
<AuthContextProvider>
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/login" element={<LoginPage />}></Route>
<Route path="/register" element={<RegisterPage />}></Route>
</Routes>
</AuthContextProvider>
);
}
export default App;
AuthContextProvider함수를 <>에 담아서 Routes
부터 아래의 컴포넌트들을 감싸주고 import문을 작성해준다.
// src/context/AuthContext.js
import { createContext } from "react";
export const AuthContext = createContext();
const AuthContextProvider = ({children}) => {
return (
<AuthContext.Provider value>
{children}
</AuthContext.Provider>
)
}
export default AuthContextProvider;
AuthContextProvider에서 필요한 value값을 선언하여 사용할 수 있고,
함수를 사용하여 값을 업데이트 할 수 도있다.
초기 로그인 정보 -> 로그인 상태가 아님
import { createContext } from "react"
export const AuthContext = createContext();
function AuthContextProvider ({children}) => {
const [isAuth,setIsAuth] = useState(false);
const AuthContextData = {
isAuth,
}
return (
<AuthContext.Provider value={AuthContextData}>
{children}
</AuthContext.Provider>
)
export default AuthContextProvider;
로그인 유무정보가 담긴 값을 isAuth
라 선언하고
초기사용자는 로그인정보가 없으니 state 값을 false
로 한다.
isAuth
값을 AuthContextData
로 객체로 선언하고
Provider
나눠줄 value
는 isAuth값
을 받기위해 AuthContextData
의 값을 받는다.
이제 children
에 들어있는 모든 컴포넌트안에서 isAuth
값을 받을 수 있다.
isAuth
)를 업데이트해주는 함수Customer.isAuthenticated | JavaScript API 레퍼런스 | 클레이풀
설치 및 코드 연동하기 | 클레이풀 ( options 값 안내 )//클레이풀 고객로그인여부 확인 API var Customer = Clayful.Customer; var options = { ... }; Customer.isAuthenticated(options, function(err, result) { if (err) { // Error case console.log(err.code); } var headers = result.headers; var data = result.data; console.log(data); });
Customer.isAuthenticated 란 함수가 options값을 받고 고객의 로그인여부를 판단한다. AuthContext.js 파일에 이 코드를 추가한다.
import { useState , createContext } from 'react';
import Clayful from 'clayful/client-js';
export const AuthContext = createContext();
function AuthContextProvider ({children}) {
const [isAuth,setIsAuth] = useState(false);
//클레이풀 고객로그인여부 확인 API
const isAuthenticated = () => {
var Customer = Clayful.Customer;
var options = {
customer:localStorage.getItem("accessToken")
};
Customer.isAuthenticated(options, function(err, result) {
if (err) {
// Error case
console.log(err.code);
setIsAuth(flase);
}
var headers = result.headers;
var data = result.data;
if (isAuthenticated) {
setIsAuth(true)
} else {
setIsAuth(false)
}
console.log(data);
});
}
const AuthContextData = {
isAuth,
isAuthenticated
}
return(
<AuthContext.Provider vlaue={AuthContextdata}>
{children}
</AuthContext.Provider>
)
}
const isAuthenticated = ()=>{}
클레이풀 코드를 함수로 선언해준다.
import Clayful from 'clayful/client-js';
클레이풀 서비스를 이용하기 위해 Clayful
을 import
한다.
options 에는 고객이 브라우저(로컬스토리지)에 가지고 있는 토큰을 넣는다.
customer:localStorage.getItem("accessToken")
집어넣을때setItem
와 반대로 getItem
을 써서 토큰값을 localStorage
로 부터 꺼낸다.
var options = {
customer : localStorage.getItem("accessToken")
};
if (err)
서버에서 에러를 응답했을때 setIsAuth
의 state
를 false
로 설정한하고 return
으로 반환 후 종료한다.if (err) {
// Error case
console.log(err.code);
setIsAuth(flase);
return;
}
if (isAuthenticated)
서버에서 사용자 토큰값이 맞다고 판단하면 setIsAuth(true)
의 state
를 true
로 설정한다. 아니라면 false
로 설정한다. var headers = result.headers;
var data = result.data;
if (isAuthenticated) {
setIsAuth(true)
} else {
setIsAuth(false)
}
AuthContextData
에 state를 업데이트 시켜주는 함수인isAuthenticated
을 넣어준다. const AuthContextData = {
isAuth,
isAuthenticated
}
이로서 Provider 내의 모든 컴포넌트에서 isAuth의 정보를 받아볼수있고 업데이트도 할수 있게 되었다.
import {useNavigate} from 'react-router-dom';
const navigate = useNavigate();
...
const signOut = () => {
setIsAuth(false);
customer : localStorage.removeItem("accessToken");
navigate("/login");
...
const AuthContextData = {
isAuth,
isAuthenticated,
signOut,
}
signOut 함수 생성
실행시 setIsAuth
값을 false
로 ->로그아웃
customer.localStorage.removeItem("accessToken")
-> 로컬 토큰 삭제
navigate("/login")
-> 로그아웃 시 로그인 페이지로 이동시킴
AuthContextData
에 signOut 함수 추가
import React, { createContext, useState } from "react";
import { useNavigate } from "react-router-dom";
import Clayful from "clayful/client-js";
export const AuthContext = createContext();
const AuthContextProvider = ({children}) => {
const navigate = useNavigate();
const [isAuth,setIsAuth] = useState(false);
//클레이풀 고객로그인여부 확인 API
const isAuthenticated = () => {
var Customer = Clayful.Customer;
var options = {
customer : localStorage.removeItem("accessToken")
};
Customer.isAuthenticated(options, function(err, result) {
if (err) {
// Error case
console.log(err.code);
setIsAuth(false);
return;
}
var headers = result.headers;
var data = result.data;
if (isAuthenticated) {
setIsAuth(true);
} else {
setIsAuth(false);
}
console.log(data);
});
}
const signOut = () => {
setIsAuth(false);
customer : localStorage.removeItem("accessToken");
navigate("/login");
}
const AuthContextData = {
isAuth,
isAuthenticated,
signOut,
}
return (
<AuthContext.Provider value={AuthContextData}>
{children}
</AuthContext.Provider>
)
}
export default AuthContextProvider;
AuthContext.js 파일의 로그인유지,아웃 context를 login.js 컴포넌트에서 사용해보자.
//App.js
import './App.css';
import React from 'react';
import { Route, Routes } from 'react-router-dom';
import LandingPage from './pages/LandingPage/LandingPage';
import LoginPage from './pages/LoginPage/LoginPage';
import RegisterPage from './pages/RegisterPage/RegisterPage';
import AuthContextProvider from './context/AuthContext';
function App() {
return (
<AuthContextProvider>
<Routes>
<Route path="/" element={<LandingPage />}></Route>
<Route path="/login" element={<LoginPage />}></Route>
<Route path="/register" element={<RegisterPage />}></Route>
</Routes>
</AuthContextProvider>
);
}
export default App;
App.js에서 AuthContextProvider
가 <Route path="/login" element={<LoginPage />}></Route>
를 감싸고 있기 때문에 loginPage
컴포넌트에서도 AuthContext.js
의 Context
를 사용할 수 있다.
// /src/components/login.js
import React, { useContext, useState } from 'react'
import { Link , useNavigate } from 'react-router-dom'
import Clayful from 'clayful/client-js'
import { AuthContext } from '../../context/AuthContext';
function LoginPage() {
const navigate = useNavigate();
const [email, setEmail] = useState("")
const [password, setPassword] = useState("")
//컨텍스트 불러오기
const {isAuthenticated} = useContext(AuthContext);
const handleEmailChange = (e) => {
setEmail(e.target.value);
}
const handlePasswordChange = (e) => {
setPassword(e.target.value);
}
const handleSubmit = (e) => {
e.preventDefault()
var Customer = Clayful.Customer;
var payload = {
// userId: 'user_id',
email,
password,
};
Customer.authenticate(payload, function(err, result) {
if (err) {
// Error case
console.log(err.code);
}
var data = result.data;
console.log(data);
localStorage.setItem('cutomerUid',data.customer)
localStorage.setItem('accessToken',data.token)
navigate("/")
isAuthenticated();
});
}
return (
<div className="auth-wrapper">
<section>
<h1 className="sr-only">로그인 페이지</h1>
<h2><span className="green">로그인</span> 하고 특별한 혜택누리기</h2>
<p className='gray'>계정을 잊어버리셨나요? <Link to="javascript:void(0)" className="green">같이 찾으러 가요!</Link></p>
<form onSubmit={handleSubmit}>
<label className="gray" for="email">
<input
onChange={handleEmailChange} name="email" placeholder="ID를 입력해주세요" type="email" value={email} />
</label>
<label className="gray" for="email">
<input
onChange={handlePasswordChange} placeholder="비밀번호를 입력해주세요" type="password" value={password} />
아기사자 ID는 심바, 사바나, 치타는웃고있다 서비스에 로그인할때 사용되는 Email 주소에요.
</label>
<p className='gray'>아기사자 서비스가 처음이신가요?<Link to="register" className="green"> 계정 만들러가기!</Link></p>
<button type="submit">VVIP 나가신다!</button>
</form>
</section>
</div>
)
}
export default LoginPage
useContext
로 컨텍스트를 불러온다. const context = useContext(contextValue)
loginPage
함수 컴포넌트 안에서
const {isAuthenticated} = useContext(AuthContext);
로 사용할 컨텍스트를 불러온다.
import AuthContextProvider from './context/AuthContext';
로 컨텍스트를 import한다.
navigate('/')로 루트페이지로 날리는 다음 코드에 isAuthenticated() 함수를 추가한다.
export const AuthContext = createContext;
에서 ()를 빼먹었다.export const AuthContext = createContext();