elice/WIL

[week_09] React 문법 | React-Router-Dom v6, useReducer, useContext

건망디 2022. 3. 13. 17:02

1. React-Router-Dom 라이브러리 v6

1-1. Routes, element

Router ➡ Routes ➡ Route 구조로 구현하고, element props를 사용해서 렌더링할 컴포넌트를 전달한다.

import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/" element={<Portfolio />} />
        <Route path="/login" element={<LoginForm />} />
        <Route path="/register" element={<RegisterForm />} />
      </Routes>
    </Router>
  );
}

1-2. useNavigate

특정 경로로 이동할 때는 useNavigate 훅을 사용한다.

const navigate = useNavigate()

navigate("/login")
navigate("/login", {replace: true})

1-3. path="*"

SPA 라우팅에 걸러지지 않는 링크의 경우 path="*"를 사용한다.

<Router>
    <Routes>
        <Route path="/" element={<Portfolio />} />
        <Route path="/login" element={<LoginForm />} />
        <Route path="/register" element={<RegisterForm />} />
        <Route path="*" element={<NotFound />} />
    </Routes>
</Router>

위 예시의 경우, 사용자가 접속한 url이 ~/, ~/login, ~/register 중 하나가 아닐때 자동으로 NotFound 컴포넌트를 렌더링하도록 만든다.

 

2. useReducer

2-1. useReducer 문법

✨ useReducer의 규칙

1️⃣ state, reducer, dispatch, action, action.type, action.payload
2️⃣ action을 dispatch하면 state가 바뀐다.
3️⃣ action.type의 종류에 따라 reducer가 state를 바꾼다.
4️⃣ reducer가 state를 바꿀 때, action.payload의 데이터를 사용한다.

2-2. useReducer 활용 방법

1) reducer 함수 생성

export function loginReducer(userState, action) {
  switch (action.type) {
    case "LOGIN_SUCCESS":
      return {
        ...userState,
        user: action.payload,
      };
    case "LOGOUT":
      return {
        ...userState,
        user: null,
      };
    default:
      return userState;
  }
}

2) useReducer를 사용해서 상태, dispatch 생성

const [userState, dispatch] = useReducer(loginReducer, {user: null});

3) 로그인 시 dispatch 사용: dispatch 함수를 실행해서, 객체(action)을 reducer 함수로 보냄

const res = await Api.post("user/login", { email, password, });

const user = res.data;

dispatch({ type: "LOGIN_SUCCESS", payload: user, });

 

3. useContext

1) createContext로 Context를 생성하고, 해당 Context를 export

export const UserStateContext = createContext(null);
export const DispatchContext = createContext(null);

2) Context.provider 컴포넌트로 다른 컴포넌트를 감싼다.

<Context.provider value={다른 컴포넌트에서 쓸 변수}>
  <다른 컴포넌트 />
</Context.provider>
function App() {
  // useReducer 훅을 통해 userState 상태와 dispatch함수를 생성함.
  const [userState, dispatch] = useReducer(loginReducer, {
    user: null,
  });

  return (
    <DispatchContext.Provider value={dispatch}>
      <UserStateContext.Provider value={userState}>
        <Router>
          <Header />
          <Routes>
            <Route path="/login" element={<LoginForm />} />
          </Routes>
        </Router>
      </UserStateContext.Provider>
    </DispatchContext.Provider>
  );
}

3) 다른 컴포넌트에서 context를 import하고, useContext를 사용한다.

import { DispatchContext } from "App";

function LoginForm() {
  const dispatch = useContext(DispatchContext);

  const handleSubmit = async (e) => {
    e.preventDefault();

    try {
      // "user/login" 엔드포인트로 post요청함.
      const res = await Api.post("user/login", {
        email,
        password,
      });
      // 유저 정보는 response의 data임.
      const user = res.data;

      // dispatch 함수를 이용해 로그인 성공 상태로 만듦.
      dispatch({
        type: "LOGIN_SUCCESS",
        payload: user,
      });

  return (
        <div></div>
    )
}