[12일차] 스크롤 높이에 따라 헤더 색상 다르게 보여주기(Redux/toolkit)

h-a-n-a·2023년 8월 18일

💫Ed Sheeran

목록 보기
12/24

홈페이지 전역에서 스크롤 높이에 따라 헤더의 색상을 다르게 보여주는 기능을 사용하고 싶었다. 전역 상태관리를 위해 Redux/toolkit을 사용하면서 오늘 다시 한번 정리하는 글!

1. headerSlice 생성

headerSlice에서는 show 라는 불리언 속성에 따라 show가 false일 때는 원래 흰색 글씨의 헤더, true일 때는(스크롤 높이가 일정길이 이상 내려갔을 때) 글씨가 검정색으로 변하게 할 것이다.

//headerSlice.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';

export interface HeaderState {
  show: boolean;
}

const initialState: HeaderState = {
  show: false,
};

const headerSlice = createSlice({
  name: 'header',
  initialState,
  reducers: {
    setShow: (state, action: PayloadAction<boolean>) => {
      state.show = action.payload;
    },
  },
});

export const { setShow } = headerSlice.actions;
export default headerSlice.reducer;

reducers에서 setShow 라는 액션을 정의한다. PayloadAction을 사용하고, boolean 타입을 받는다. setShow 액션이 실행될 때, state 객체의 show 속성이 action.payload 값으로 설정된다!

2. store에 등록하기

//store.ts
import { configureStore } from '@reduxjs/toolkit';
import headerReducer from './slice/headerSlice';

const store = configureStore({
  reducer: {
    header: headerReducer,
  },
});

export type RootState = ReturnType<typeof store.getState>;

export type AppDispatch = typeof store.dispatch;
export default store;

타입스크립트로 redux/toolkit을 작성해보기는 처음이라서, Rootstate를 작성해주지 않아 애를 먹었다.

export type RootState = ReturnType<typeof store.getState>

앞으로 Typescript로 redux/toolkit을 사용할 경우, store는 그냥 아래에 있는 걸 template으로 작성하면 된다.

import { configureStore } from '@reduxjs/toolkit'

export const store = configureStore({
  reducer: {},
})

export type RootState = ReturnType<typeof store.getState>
export type AppDispatch = typeof store.dispatch

위에서 export type RootState = ReturnType<typeof store.getState>을 작성한 것은 RootState와 Dispatch의 타입을
reducer에 state slice를 추가한 store의 타입을 추론해 지정한 것이다.

  1. 앱 전체를 Provider로 감싸주기
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { Global, Theme } from '@emotion/react';
import GlobalStyle from './styles/globalStyle';
import { ThemeProvider, createTheme } from '@mui/material/styles';
import { Provider } from 'react-redux';
import store from './store/store';
oauth/google';

ReactDOM.createRoot(document.getElementById('root')!).render(
  <React.StrictMode>
        <Provider store={store}>
          {' '}
          <ThemeProvider theme={theme}>
            <Global styles={GlobalStyle} />
            <App />{' '}
          </ThemeProvider>
        </Provider>
  </React.StrictMode>
);
  1. 사용할 컴포넌트에서 headerSlice 가져다 쓰기
import { StyledHeader, LogoWrapper } from './style';
import Logo from '../Logo';
import Nav from '../Nav';
import { useEffect } from 'react';
import { setShow, HeaderState } from '@src/store/slice/headerSlice';
import { useDispatch, useSelector } from 'react-redux';
//redux 스토어와 상호작용하기 위해 useDispatch, useSelector 훅 가져오기!
function Header() {
  const dispatch = useDispatch();
  const show = useSelector(
    (state: { header: HeaderState }) => state.header.show
  );
  //headerSlice에서 show 속성 값 가져오기
  useEffect(() => {
    const handleScroll = () => {
      if (window.scrollY > 114) {
        dispatch(setShow(true));
      } else {
        dispatch(setShow(false));
      }
    };

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, [dispatch]);

  return (
    <StyledHeader show={show}>
      <LogoWrapper>
        <Logo show={show} />
      </LogoWrapper>
      <Nav show={show} />
    </StyledHeader>
  );
}
export default Header;

확실히 그냥 redux만 쓸때보다는 RTK를 쓰는 것이 훨씬 코드 읽기나 사용법도 간단한 것 같다!


참고사이트: https://velog.io/@letthere/react-Redux-Toolkit-%EC%82%AC%EC%9A%A9-%EA%B0%80%EC%9D%B4%EB%93%9CTypeScript

[Redux] Redux Toolkit 시작하기

profile
하루하루가 연습이니 내일은 더 강해질 겁니다

0개의 댓글