[React JS] 2. React.js

 

1. ๋ฆฌ์•กํŠธ๋ž€?

- ํŽ˜์ด์Šค๋ถ์—์„œ ๋งŒ๋“  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (2013)- Components๋กœ ์ด๋ค„์ ธ์žˆ์–ด reusable / ์žฌ์‚ฌ์šฉ์„ฑ์ด ๋›ฐ์–ด๋‚จ   ex) like๊ธฐ๋Šฅ, comment.js ๋ฅผ ๋‹ค๋ฅธ ๋ฐ์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅ!

 

Real DOM VS Virtual DOMReal DOM - ๋งŒ์•ฝ 10๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ ์ค‘ ํ•œ๊ฐ€์ง€์˜ ๋ฆฌ์ŠคํŠธ๋งŒ update ๋จ- ์ „์ฒด ๋ฆฌ์ŠคํŠธ๋ฅผ ๋‹ค์‹œ reload ํ•ด์•ผ๋จ -> super expensive

 

Virtual DOM- ๋งŒ์•ฝ 10๊ฐœ์˜ ๋ฆฌ์ŠคํŠธ๊ฐ€ ์ค‘ ํ•œ๊ฐ€์ง€์˜ ๋ฆฌ์ŠคํŠธ๋งŒ update ๋จ- ๊ทธ ๋ฐ”๋€ ํ•œ๊ฐ€์ง€ ์•„์ดํ…œ๋งŒ DOM์—์„œ ๋ฐ”๊ฟ”์คŒ

 

์–ด๋–ป๊ฒŒ? -> virtual dom์—์„œ ์Šค๋ƒ…์ƒท ์ฐ์–ด๋‘๊ณ  ์‚ดํŽด๋ณธ ๋’ค ๋ฐ”๋€ ๋ถ€๋ถ„๋งŒ real dom์—์„œ ๋ฐ”๊ฟ”์คŒ

 


2. Create React App์œผ๋กœ ๋ฆฌ์•กํŠธ ์‹œ์ž‘ํ•˜๊ธฐ

- ์›๋ž˜ babel(์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ• ์ง€์›ํ•˜์ง€ ์•Š๋Š” ๋ถ€๋ผ์šฐ์ €์—์„œ ์ตœ์‹  ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฌธ๋ฒ•์„ ๋ณผ ์ˆ˜ ์žˆ๊ฒŒ ๋ณ€ํ™˜์‹œ์ผœ์คŒ)์ด๋‚˜ webpack(์›น์‚ฌ์ดํŠธ ๋งŒ๋“ค๋•Œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ, ํ”„๋ ˆ์ž„์›Œํฌ๋“ค์„ ๋ฒˆ๋“ค=๋ฌถ์–ด์ฃผ๋Š” ์—ญํ•  = ๋งŽ์€ ๋ชจ๋“ˆ๋“ค์„ ๊ฐ„๋‹จํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์คŒ)

 

cd client

npx create-react-app .

dot : client ์•ˆ์—๋‹ค ์„ค์น˜ํ•œ๋‹ค๋Š” ์˜๋ฏธ


3. npm npx

npm(node package manager)

1) ์˜คํ”ˆ์†Œ์Šค ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ๋‹ด๊ณ ์žˆ๋Š” online repository

2) version management, dendency management ๋ฅผ ์œ„ํ•œ command-line utility

 

local VS globally

๋กœ์ปฌ์— ๋ฐ›์„๋• node_modules์— ๋ฐ›์•„์ง

-g ํ”Œ๋ž˜๊ทธ ์ฃผ๋ฉด ํ”„๋กœ์ ํŠธ ์•ˆ์ด ์•„๋‹ˆ๋ผ ์ปดํ“จํ„ฐ ์ž์ฒด์— ๋ฐ›์•„์ง€๋Š” ๊ฒƒ

 

npx

- ์›๋ž˜๋Š” create app ์‚ฌ์šฉํ•  ๋•Œ ์ปดํ“จํ„ฐ์— ๋ฐ›์•˜์ง€๋งŒ npx๋ฅผ ํ†ตํ•ด npm registry์—์„œ ์ฐพ์•„์„œ ๋‹ค์šด๋กœ๋“œ ์—†์ด ์‹คํ–‰

- ์žฅ์  : disk space ๋‚ญ๋น„ X & ํ•ญ์ƒ ์ตœ์‹ ๋ฒ„์ „ ์‚ฌ์šฉ ๊ฐ€๋Šฅ


4. ๊ตฌ์กฐ ์„ค๋ช…

App.js

- ์—ฌ๊ธฐ์„œ ํŽ˜์ด์ง€ ๋ Œ๋”๋ง

 

index.js

- ์—ฌ๊ธฐ ์•ˆ์— App ์ปดํฌ๋„ŒํŠธ๊ฐ€ ๋“ค์–ด๊ฐ„๊ฒƒ

- document.getElementById (index.html ์˜ root์— ๋ณด์—ฌ์ค„ ๊ฒƒ์„ ์ •์˜ํ•ด์ฃผ๋Š” ๊ฒƒ)

 

webpack์ด src๋งŒ ๊ด€๋ฆฌํ•ด์คŒ -> src๋ถ€๋ถ„์— ์ด๋ฏธ์ง€ ํŒŒ์ผ์„ ๋„ฃ์–ด์ค˜์•ผํ•จ! (public์ด ์•„๋‹ˆ๋ผ)


5. CRA to Our Boilerplate

hoc : ์ปดํฌ๋„ŒํŠธ์•ˆ์— ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๊ฐ–๋Š” function

ex) Auth(HOC)๊ฐ€ ์žˆ๊ณ  Admin Component๊ฐ€ ์žˆ์„ ๋•Œ Auth ์ปดํฌ๋„ŒํŠธ์—์„œ ํ•ด๋‹น ์ปดํฌ๋„ŒํŠธ ์ ‘๊ทผ ๊ฐ€๋Šฅ ์—ฌ๋ถ€ ์ฒดํฌ


6. React Router Dom

App.js์— router ๋งŒ๋“ค๊ธฐ

cd client
npm install react-router-dom --save
import React from "react";
import {
  Route,
  Routes,
  Link,
  BrowserRouter
} from "react-router-dom";

function Home() {
  return <h2>Home</h2>;
}

function About() {
  return <h2>About</h2>;
}

function Users() {
  return <h2>Users</h2>;
}



function App() {
  return (
    <BrowserRouter>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/about">About</Link>
          </li>
          <li>
            <Link to="/users">Users</Link>
          </li>
        </ul>

        <hr />
        {/* A <Switch> looks through its children <Route>s and
          renders the first one that matches the current URL. */}
        <Routes>
          <Route path="/about" element={About()}>
            <Route />
          </Route>
          <Route path="/users" element={Users()}>
            <Route />
          </Route>
          <Route path="/" element={Home()}>
            <Route />
          </Route>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

7. Flow & Axios

์š”์ฒญ ๋ณด๋‚ผ๋•Œ Axios๋ฅผ ํ†ตํ•ด ๋ณด๋ƒ„ (Ajax ๊ฐ™์€ ๊ฒƒ)

cd client
npm install axios --save

server

// ํ”„๋ก ํŠธ์— ํ•ด๋‹น ๋ฉ”์‹œ์ง€ ์ „๋‹ฌ
app.get("/api/hello", (req, res) => {
  res.send("์•ˆ๋…•ํ•˜์„ธ์š”");
});

client

function LandingPage() {
  // api ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๊ณ  (index.js)
  useEffect(() => {
    axios.get("/api/hello").then((response) => console.log(response.date));
  }, []);
  return <div>LandingPage</div>;
}

8. CORS์ด์Šˆ, Proxy ์„ค์ •

CORS : Cross-Origin Resource Sharing

* ๋‹ค๋ฅธ ํฌํŠธ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ๋Š” ๋‘ ์„œ๋ฒ„ ์‚ฌ์ด ์•„๋ฌด ์„ค์ •์—†์ด request ๋ณด๋‚ผ ์ˆ˜ ์—†๊ฒŒ ๋ง‰์€ ๊ฒƒ

 

proxy ๋ชจ๋“ˆ ๋‹ค์šด

cd client
npm install http-proxy-middleware --save

setupProxy.js

const { createProxyMiddleware } = require('http-proxy-middleware');

module.exports = function(app){
  app.use(
      createProxyMiddleware('/api', {
          target: 'http://localhost:5000/',
          changeOrigin: true
      })
  )
};

9. Concurrently

ํ”„๋ก ํŠธ/๋ฐฑ ์„œ๋ฒ„ ๋™์‹œ์— ์ผœ๊ธฐ ์œ„ํ•ด

npm install concurrently --save

 

package.json script์— ์ถ”๊ฐ€

"dev": "concurrently \"npm run backend\" \"npm run start --prefix client\""

10. CSS Framework ์ข…๋ฅ˜ for React.js

Ant Design: https://ant.design/ 

cd client
npm install antd --save
npm install antd@^4.24.0 --save

11. Redux

Redux : ์ƒํƒœ ๊ด€๋ฆฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ (predictable state container)

 

state?

 

Props VS State

1) Props (properties)

- ์ปดํฌ๋„ŒํŠธ ๋‹จ๋ผ๋ฆฌ ์ฃผ๊ณ ๋ฐ›์„๋•Œ prop ํ™œ์šฉ

- ๋ถ€๋ชจ์—์„œ ์ž์‹ ์ปดํฌ๋„ŒํŠธ์—๋งŒ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Œ

- ๋ถ€๋ชจ์—์„œ ์ž์‹์œผ๋กœ ๊ฑด๋‚ด๋ฐ›์€ ๊ฐ’์€ ๋ฐ”๋€” ์ˆ˜ ์—†์Œ (๋‹ค์‹œ ๋ถ€๋ชจ์—์„œ ์ž์‹์—๊ฒŒ ๊ฑด๋‚ด์ค˜์•ผ ๋ฐ”๋€œ)

- immutable

<ChatMessages
  messages={messages}
  currentMember={member}
/>

 

2) State

- ์ปดํฌ๋„ŒํŠธ ์•ˆ์—์„œ ๋ฐ์ดํ„ฐ ๊ตํ™˜

- ๊ฐ’ ๋ฐ”๋€Œ๋ฉด ๋ฆฌ๋žœ๋”๋ง ๋จ

- mutable

state = {
  message: '',
  attachFile: undefined,
  openMenu: false
}

 

-> redux๋Š” state๋ฅผ ๊ด€๋ฆฌ

 

- ํ•œ๋ฐฉํ–ฅ์œผ๋กœ๋งŒ ํ๋ฆ„

 

1)Action

- ๊ฐ์ฒด

- ๋ฌด์—‡์ด ์ผ์–ด๋‚ฌ๋Š”์ง€ ์„ค๋ช…

{ type: 'LIKE_ARTICLE', articleId: 42 }

 

2)Reducer

- action์œผ๋กœ ์ธํ•ด ์ด์ „ state๊ณผ ๋ณ€ํ•ด์ง„ state ๋ฆฌํ„ด

(previousState, action) => nextState

 

3)Store

- ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ state์„ ๊ฐ์‹ธ์ฃผ๋Š” ์—ญํ• 

- ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๋ฉ”์„œ๋“œ ์žˆ์Œ

 

Setting Up Redux

cd client
npm install redux react-redux redux-promise redux-thunk --save

* redux-promise & redux-thunk 

- ๋ฏธ๋“ค์›จ์–ด

- ํ•„์š”ํ•œ ์ด์œ 

> ๋ฆฌ๋•์Šค๋ฅผ ์ž˜ ์“ธ ์ˆ˜ ์žˆ๊ฒŒ ๋„์™€์ฃผ๋Š” ์—ญํ•  

> redux store์˜ state๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๋ฐฉ๋ฒ•์ด dispatch(action)

   -> action์€ ๊ฐ์ฒด ํ˜•์‹์ด์–ด์•ผํ•จ

   -> store๋Š” promise/function ํ˜•ํƒœ๋กœ ๋ฐ›์„ ๋•Œ๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—

   -> promise๋Š” promise ๋Œ€์ฒ˜ํ•˜๋Š” ๋ฒ• ์•Œ๋ ค์คŒ

   -> thunk๋Š” dispatch์— function ๋ฐ›๋Š” ๋ฒ• ์•Œ๋ ค์ฃผ๋Š” ๊ฒƒ

 

client src index.js

import { Provider } from "react-redux";
import { applyMiddleware, createStore } from "redux";
import promiseMiddleware from "redux-promis";
import ReduxThunk from "redux-thunk";
import Reducer from './_reducers';
import "antd/dist/antd.css";

const createStoreWithMiddleware = applyMiddleware(
  promiseMiddleware,
  ReduxThunk
)(createStore);

root.render(
  <Provider
    store={createStoreWithMiddleware(
      Reducer,
      window.__REDUX_DEVTOOLS_EXTENSION__ &&
        window.__REDUX_DEVTOOLS_EXTENSION__()
    )}
  >
    <App />
  </Provider>
);

_reducers ํด๋”์— index.js ์ถ”๊ฐ€

import { combineReducers } from "redux";
//import user from "./user_reducer";

const rootReducer = combineReducers({});

export default rootReducer;

 

combineReducers

- store๊ฐ€ ์žˆ๋Š”๋ฐ ์•ˆ์— ์—ฌ๋Ÿฌ๊ฐ€์ง€ reducers ์žˆ์Œ (reducer ํ•˜๋Š” ์ผ์ด state๊ฐ€ ์–ด๋–ป๊ฒŒ ๋ณ€ํ•˜๋Š”์ง€ ๋ณด์—ฌ์ฃผ๊ณ  ๋ณ€ํ•œ ๋งˆ์ง€๋ง‰ ๊ฐ’์„ returnํ•˜๋Š” ์—ญํ• )

- combineReducers ์ด์šฉํ•ด์„œ ๋‚˜๋ˆ ์ง„ rootReducer๋กœ ํ•˜๋‚˜๋กœ ํ•ฉ์ณ์ฃผ๋Š” ์—ญํ• 

 

chrome extension - Redux Dev Tools ๋‹ค์šด


12. React Hooks

React Component

1) Class Component

- ๋” ๋งŽ์€ ๊ธฐ๋Šฅ ์‚ฌ์šฉ ๊ฐ€๋Šฅ

- ์ฝ”๋“œ๊ฐ€ ๊ธธ์–ด์ง€๊ณ  ๋ณต์žกํ•ด์ง

- ์„ฑ๋Šฅ ๋Š๋ ค์ง

 

2) Functional Component

- ์ œ๊ณต ๊ธฐ๋Šฅ ํ•œ์ •๋จ

- ์ฝ”๋“œ๊ฐ€ ๊ฐ„๋‹จํ•ด์ง

- ์„ฑ๋Šฅ์ด ๋นจ๋ผ์ง

 

Functional Component์—์„œ ๋ชป์“ฐ๋Š” ๊ธฐ๋Šฅ

๋ฆฌ์•กํŠธ ์ƒ์„ฑ ์ˆœ์„œ

- constructor ์‹คํ–‰ (state ๋ถ€์—ฌ)

- render (DOM์— ์•Œ๋งž๊ฒŒ ๋„ฃ์–ด์„œ ๋žœ๋”๋ง)

- ComponentMount ํ†ตํ•ด์„œ ๋ฐ์ดํ„ฐ ๊ฐ€์ ธ์˜ด

ใ„ด ์œ„ ๊ธฐ๋Šฅ๋“ค์„ ์›๋ž˜ ๋ชป์ผ์Œ

 

*HTML DOM

 

React Hooks update (16.8v ์ด์ƒ)

-> functional component์—์„œ ๋ผ์ดํ”„ ์‚ฌ์ดํด / state ๋ถ€์—ฌ ๋‹ค ์‚ฌ์šฉ ๊ฐ€๋Šฅ

 

๋น„๊ต

hook์ด ๋‚˜์˜ค๋ฉด์„œ useEffect๋กœ ๋ผ์ดํ”„์Šคํƒ€์ผ ์‚ฌ์šฉ๊ฐ€๋Šฅ (์ตœ์‹  hook ๋งŽ์ด ์”€)


13. LoginPage ๋งŒ๋“ค๊ธฐ & RegisterPage ๋งŒ๋“ค๊ธฐ

LoginPage.js

import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { loginUser } from "../../../_actions/user_action";
import { useNavigate } from "react-router-dom";

function LoginPage() {
  const dispatch = useDispatch();

  const navigate = useNavigate();

  // Email state์„
  const [Email, setEmail] = useState("");
  const [Password, setPassword] = useState("");

  const onEmailHandler = (event) => {
    setEmail(event.currentTarget.value);
  };

  const onPasswordHandler = (event) => {
    setPassword(event.currentTarget.value);
  };

  const onSubmitHandler = (event) => {
    // ๋กœ๊ทธ์ธ ๋ฒ„ํŠผ ๋ˆ„๋ฅด๋ฉด ์ด ํ•จ์ˆ˜์—์„œ ํ•ด์•ผํ•  ์ผ์„ ํ•˜์ง€ ์•Š๊ณ  ํŽ˜์ด์ง€๊ฐ€ ๋ฆฌํ”„๋ ˆ์‹œ ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ
    event.preventDefault();

    let body = {
      email: Email,
      password: Password,
    };

    // dispatch ์ด์šฉํ•ด์„œ action์ทจํ•˜๊ณ  ๊ทธ ๋‹ค์Œ์— reducer ๋ผ์ดํ”„ ์‚ฌ์ดํด ๋Œ๊ฒŒํ•˜๋Š” ๊ฒƒ
    dispatch(loginUser(body)).then((response) => {
      if (response.payload.loginSuccess) {
        navigate("/");
      } else {
        alert("Error");
      }
    });
  };

  return (
    <div
      style={{
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        width: "100%",
        height: "100vh",
      }}
      onSubmit={onSubmitHandler}
    >
      <form style={{ display: "flex", flexDirection: "column" }}>
        <label>Email</label>
        <input type="email" value={Email} onChange={onEmailHandler} />
        <label>Password</label>
        <input type="password" value={Password} onChange={onPasswordHandler} />
        <br />
        <button type="submit">Login</button>
      </form>
    </div>
  );
}

export default LoginPage;

_actions > user_action.js

import axios from "axios";
import { LOGIN_USER } from "./types";

export function loginUser(dataTosubmit) {
  const request = axios
    .post("/api/users/login", dataTosubmit)
    .then((response) => response.data);

  return {
    // request๋ฅผ reduce์— ๋„˜๊ฒจ์ฃผ๋Š” ์ž‘์—…
    type: LOGIN_USER,
    payload: request,
  };
}

_actions > types

export const LOGIN_USER = "login_user";

_reducers > user_reducer.js

import { LOGIN_USER } from "../_actions/types";

// reduce๋Š” previousState + action = NextState๋งŒ๋“œ๋Š” ์—ญํ• 
export default function userReducer(state = {}, action) {
  switch (action.type) {
    case LOGIN_USER:
      // state๋ฅผ ๋˜‘๊ฐ™์ด ๊ฐ€์ ธ์˜ค๊ณ 
      // ... spread operator = ๋˜‘๊ฐ™์ด ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ, ๋นˆ ์ƒํƒœ
      return { ...state, loginSuccess: action.payload };

    default:
      return state;
  }
}

_reducers > index.js

import { combineReducers } from "redux";
import user from "./user_reducer";

const rootReducer = combineReducers({
  user,
});

export default rootReducer;

* RegisterPage ์—ญ์‹œ ๋™์ผํ•œ ๋ฐฉ์‹


14. Log out ๊ธฐ๋Šฅ ๋งŒ๋“ค๊ธฐ

LandingPage.js

import React, { useEffect } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";

function LandingPage() {
  // api ์„œ๋ฒ„๋กœ ๋ณด๋‚ด๊ณ  (index.js)
  const navigate = useNavigate();

  useEffect(() => {
    axios.get("/api/hello").then((response) => console.log(response.date));
  }, []);

  const onClickHandler = () => {
    axios.get("/api/users/logout").then((response) => {
      if (response.data.success) {
        navigate("/login");
      } else {
        alert("failed logout");
      }
    });
  };

  return (
    <div
      style={{
        display: "flex",
        justifyContent: "center",
        alignItems: "center",
        width: "100%",
        height: "100vh",
      }}
    >
      <h2>์‹œ์ž‘ํŽ˜์ด์ง€</h2>
      <button onClick={onClickHandler}>๋กœ๊ทธ์•„์›ƒ</button>
    </div>
  );
}

export default LandingPage;

15. Authentication

HOC (higher order component)

const EnhancedComponent = higherOrderComponent(WrappedComponent);

 

- ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ๋ฅผ ๋ฐ›์€ ํ›„ ์ƒˆ๋กœ์šด ์ปดํฌ๋„ŒํŠธ ๋ฆฌํ„ดํ•˜๋Š” function

- Auth(HOC)์— ๋‹ค๋ฅธ ์ปดํฌ๋„ŒํŠธ ์ง‘์–ด๋„ฃ์„ ์ˆ˜ ์žˆ์Œ

- Auth์— LandingPage๋ฅผ ๋„ฃ์œผ๋ฉด

-> Auth๊ฐ€ backend์— request๋ฅผ ๋‚ ๋ฆผ 

-> ํ˜„์žฌ LandingPage ๋“ค์–ด์™€์žˆ๋Š” ์‚ฌ๋žŒ์˜ ์ƒํƒœ์ •๋ณด๋ฅผ ์„œ๋ฒ„์—์„œ Auth๋กœ ๋ณด๋ƒ„

-> Auth๊ฐ€ ์š”์ฒญ ๋‚ ๋ฆฌ๋ฉด์„œ ์ƒํƒœ ๊ฐ€์ ธ์™€์„œ access Authentication ํ™•์ธ

 

hoc> auth.js

import React, { useEffect } from "react";
import { useDispatch } from "react-redux";
import { auth } from "../_actions/user_action";
import { useNavigate } from "react-router-dom";

// specificComponent = Page
// option
// null : ์•„๋ฌด๋‚˜ ์ถœ์ž… ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€
// true : ๋กœ๊ทธ์ธํ•œ ์œ ์ €๋งŒ ์ถœ์ž… ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€
// false : ๋กœ๊ทธ์ธํ•œ ์œ ์ €๋Š” ์ถœ์ž… ๋ถˆ๊ฐ€๋Šฅํ•œ ํŽ˜์ด์ง€
export default function (SpecificComponent, option, adminRoute = null) {
  function AuthenticationCheck(props) {
    const dispatch = useDispatch();
    const navigate = useNavigate();

    // ๋ฐฑ์—”๋“œ์— request ๋‚ ๋ ค์„œ ์‚ฌ๋žŒ์˜ state ๊ฐ€์ ธ์˜ด
    useEffect(() => {
      // ํŽ˜์ด์ง€ ์ด๋™ํ• ๋•Œ๋งˆ๋‹ค dispatch์ž‘๋™ํ•ด์„œ backend์— request๋ฅผ ์ฃผ๋Š” ๊ฒƒ
      dispatch(auth()).then((response) => {
        console.log(response);

        // ๋กœ๊ทธ์ธ ํ•˜์ง€ ์•Š์€ ์ƒํƒœ
        if(!response.payload.isAuth){
          //true์ธ๊ฒฝ์šฐ 
          if(option){
            navigate("/login");
          }
        }else{
          //๋กœ๊ทธ์ธ ํ•œ ์ƒํƒœ
          // ์–ด๋“œ๋ฏผ ํŽ˜์ด์ง€์ธ๋ฐ && isAdmin์ด  ์•„๋‹Œ๊ฒฝ์šฐ
          if(adminRoute && !response.payload.isAdmin){
            navigate("/");
          }else{
            // false์ผ ๋•Œ
            if(!option){
              navigate("/");
            }
          }
        }
      });
    }, []);

    return <SpecificComponent />;
  }

  return AuthenticationCheck;
}

App.js

import React from "react";
import { Route, Routes, Link, BrowserRouter } from "react-router-dom";

import LandingPage from "./components/views/LandingPage/LandingPage";
import LoginPage from "./components/views/LoginPage/LoginPage";
import RegisterPage from "./components/views/RegisterPage/RegisterPage";
import Auth from "./hoc/auth";

function App() {
  const NewLandingPage = Auth(LandingPage, null);
  const NewLoginPage = Auth(LoginPage, false);
  const NewRegisterPage = Auth(RegisterPage, false);

  return (
    <BrowserRouter>
      <div>
        <ul>
          <li>
            <Link to="/">Home</Link>
          </li>
          <li>
            <Link to="/login">Login</Link>
          </li>
          <li>
            <Link to="/register">Register</Link>
          </li>
        </ul>

        <hr />
        {/* A <Switch> looks through its children <Route>s and
          renders the first one that matches the current URL. */}
        <Routes>
          <Route exact path="/login" element={<NewLoginPage />}>
            <Route />
          </Route>
          <Route exact path="/register" element={<NewRegisterPage />}>
            <Route />
          </Route>
          <Route exact path="/" element={<NewLandingPage />}>
            <Route />
          </Route>
        </Routes>
      </div>
    </BrowserRouter>
  );
}

export default App;

 

  • ๋„ค์ด๋ฒ„ ๋ธ”๋Ÿฌ๊ทธ ๊ณต์œ ํ•˜๊ธฐ
  • ๋„ค์ด๋ฒ„ ๋ฐด๋“œ์— ๊ณต์œ ํ•˜๊ธฐ
  • ํŽ˜์ด์Šค๋ถ ๊ณต์œ ํ•˜๊ธฐ
  • ์นด์นด์˜ค์Šคํ† ๋ฆฌ ๊ณต์œ ํ•˜๊ธฐ