2022.05.21 토요일
라이브러리 store 이용하여, 로컬스토리지에 상태값 저장하고
리덕스 툴킷 이용하여 상태관리
yarn add @reduxjs/toolkit react-redux
import { Provider } from 'react-redux';
import { store } from './states';
const root = ReactDOM.createRoot(document.getElementById('root') as HTMLElement);
root.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<Routes />
</BrowserRouter>
</React.StrictMode>
);
툴킷 스토어
// states/index.ts
import { configureStore } from '@reduxjs/toolkit';
import search from './search';
import system from './system';
export const store = configureStore({
reducer: {
search,
system,
},
devTools: process.env.NODE_ENV !== 'production',
middleware: (getDefaultMiddleware) => getDefaultMiddleware({ serializableCheck: false }),
});
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
yarn add store
yarn add @types/store --dev
툴킷 슬라이스
// states/system.ts
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
import store from 'store';
import type { RootState } from '.';
interface SystemState {
theme: string;
}
const initialState: SystemState = {
theme: store.get('foundation.theme') || 'light',
};
const systemSlice = createSlice({
name: 'theme',
initialState,
reducers: {
setTheme: (state: SystemState, action: PayloadAction<string>) => {
const newColorSet = action.payload;
store.set('foundation.theme', newColorSet);
document.documentElement.setAttribute('color-theme', newColorSet );
state.theme = newColorSet;
},
toggleTheme: (state: SystemState) => {
const newColorSet = state.theme === 'light' ? 'dark' : 'light';
store.set('foundation.theme', newColorSet);
document.documentElement.setAttribute('color-theme', newColorSet);
state.theme = newColorSet;
},
},
});
export default systemSlice.reducer;
export const { toggleTheme } = systemSlice.actions;
export const getTheme = (state: RootState): string => state.system.theme;
// src/routes/Search/index.tsx
import styles from './search.module.scss';
import SearchBar from 'routes/Search/SearchBar';
import Recommend from 'routes/Search/Recommend';
import { useAppSelector } from 'hooks';
import { getTheme, toggleTheme } from 'states/system';
import { useDispatch } from 'react-redux';
const Search = () => {
const dispatch = useDispatch();
const theme = useAppSelector(getTheme);
const handleThemeClick = () => {
dispatch(toggleTheme());
};
return (
<main className={styles.main}>
<header>
국내 모든 임상시험 검색하고 <br />
온라인으로 참여하기
<div className={styles.rightWing}>
<button type='button' onClick={handleThemeClick}>
{theme}
</button>
</div>
</header>
<SearchBar />
<Recommend />
</main>
);
};
export default Search;
리덕스 값을 가져오려면 provider안에 있어야하기 때문에 routes에서 코드작성
마운트됐을 때 값을 가져와서 document에 setAttribute로 컬러테마를 집어넣음
// src/routes/index.tsx
import { useMount } from 'react-use';
import styles from './Routes.module.scss';
import { useAppSelector } from 'hooks';
import { getTheme } from 'states/system';
import Search from './Search';
const App = () => {
const theme = useAppSelector(getTheme);
useMount(() => {
document.documentElement.setAttribute('color-theme', theme);
});
return (
<div className={styles.app}>
<Search />
</div>
);
};
export default App;
html 꼭대기에 적용시켰으니 땡겨쓰기
:root[color-theme='dark'] & {}
// src/routes/Routes.module.scss
@use '/src/styles/mixins/flexbox';
@use '/src/styles/constants/colors';
.app {
@include flexbox.flexbox('center', 'start');
height: 100vh;
padding: 100px;
background-color: #cae9ff;
transition: 0.2s;
:root[color-theme='dark'] & {
color: colors.$WHITE;
background-color: black;
}
}
constant폴더의 컬러셋을 dark모드인지에 따라 바꿔서 넣어줄 수 있으면 좋을 것 같은데... 아직 방법은 찾지못했다 ㅠㅠ