프론트엔드/리액트 | React

리액트 웹앱 - 상단 타이틀 동적으로 적용하기 (redux 활용)

개발자R 2022. 4. 13. 16:52
반응형

어떻게 검색을 해야하는 건지, 검색을 해도 잘 안나와서 어찌저찌 개발을 했다.

앱을 쓰다보면 상단 타이틀이 페이지마다 바뀌는 UI를 본적이 있을 것이다.

예를 들어 카카오톡 같은 경우에도 친구 / 채팅 / 뷰  이런식으로 현재 페이지 이름이 상단에 나와있다.

 

그런데... 

레이아웃은 아래처럼 되어있다.

페이지는 <main> </main> 여기만 바뀌는데 <Header/> 의 속성을 어떻게 바꿀 수 있지?

<Fragment>
  <Header isShowBackArrow={true} title={title}/>
  <main className={classes.main}>{props.children}</main>
  <BottomNav />
</Fragment>

열심히 생각하다가, react의 Context API를 사용해야하나, redux를 사용해야하나 고민을 했고

redux를 활용하기로 했다.

 

우선 store 폴더를 먼저 만들어주었다.

store 폴더에 index.js 파일과 title.js 파일을 만들어준다.

title.js는 state를 관리하는 곳이고, index.js는 여러 슬라이스들을 모아서 store로 묶어준다.

 

src/store/title.js

import { createSlice } from "@reduxjs/toolkit";

const titleSlice = createSlice({
  name: "title",
  initialState: "",
  reducers: {
    setTitle(state, action) {
      return action.payload;
    },
  },
});

export const titleActions = titleSlice.actions;
export default titleSlice.reducer;

state로 관리할 것이 title밖에 없기 때문에 비교적 간단하다.

 

src/store/index.js

import { configureStore } from "@reduxjs/toolkit";

import titleReducer from "./title";

const store = configureStore({
  reducer: { title: titleReducer },
});

export default store;

지금 적용한 슬라이스는 하나밖에 없기 때문에 index.js 파일도 비교적 간단함.

 

이제 이렇게 만든걸 적용하기 위해 찐 최상위 index.js을 수정해주어야한다.

 

src/index.js

import { createRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import { Provider } from "react-redux";

import "./index.css";
import App from "./App";
import store from "./store/index";

const container = document.getElementById("root");
const root = createRoot(container);
root.render(
  <Provider store={store}>
    <BrowserRouter>
      <App />
    </BrowserRouter>
  </Provider>
);

3번째줄에서 Provider을 불러오고, 7번째줄에서 store을 불러온다.

그런 다음 Provider에 store을 적용시켜야 우리가 만든 redux store을 사용할 수 있다.

 

타이틀 변경하기

이제 어떤 페이지에 들어갔을 때 타이틀을 변경해주어야겠죠?

저는 Task를 등록하는 NewTask.js 페이지에 들어갔을 때 "기록하기"라는 타이틀이 나오도록 했습니다.

/src/pages/tasks/NewTask.js

import React, { Fragment, useEffect } from "react";
import { useDispatch } from "react-redux";
import { titleActions } from "../../store/title";

const NewTask = () => {
  const dispatch = useDispatch();
  useEffect(() => {
    dispatch(titleActions.setTitle("기록하기"));
  }, []);

  return (
    <Fragment>
      /*내용물 생략*/
    </Fragment>
  );
};

export default NewTask;

이 페이지에 접근하는 딱 처음만 필요하기 때문에 useEffect를 사용했습니다.

 

마지막으로 헤더에 타이틀을 넣어야겠죠??

저는 Layout 파일에서 했습니다.

Header 파일에서 해도 될거같네요!

/src/components/Layout/Layout.js

import { Fragment } from "react";
import { useSelector } from "react-redux";

import BottomNav from "./BottomNav";
import Header from "./Header";
import classes from "./Layout.module.css";

const Layout = (props) => {
  const title = useSelector((state) => state.title);
  return (
    <Fragment>
      <Header isShowBackArrow={true} title={title} />
      <main className={classes.main}>{props.children}</main>
      <BottomNav />
    </Fragment>
  );
};

export default Layout;

useSelector을 이용하여 title의 최신값을 가져오면 끝!

 

 

아래와 같이 하단 네비게이션으로 페이지를 이동할 때마다 타이틀이 정상적으로 바뀝니다!

 

그럼 끝~

얼른 내용물 예쁘게 바꿔야겠네요 ㅎㅎㅎ

반응형