An opinionated guide on how to theme your react application with SCSS and Redux.
Steps to follow
Create a new app with create-react-app
npx create-react-app myapp
Add structure to your app:
...
src
store
theme
theme.slice.js
theme.actions.js
rootReducer
styles
_themes.scss
_themify.scss
components
layout
layout.jsx
layout.scss
page
home
home.jsx
about
about.jsx
App.js
...
Add these packages to the app
npm i @reduxjs/toolkit redux node-sass react-router-dom react-redux --save
Create the theme slice
// theme.slice.js
import { createSlice } from '@reduxjs/toolkit'
import { uiActions } from './ui.actions'
export const uiSlice = createSlice({
name: 'ui',
initialState: 'light-theme',
reducers: uiActions
})
export const { toggleTheme } = uiSlice.actions
export default uiSlice.reducer
Create the theme action
// theme.action.js
export const uiActions = {
toggleTheme: state => {
console.log(state);
return state === 'dark-theme' ? 'light-theme' : 'dark-theme';
}
};
Create the reducer
// rootReducer.js
import { configureStore } from '@reduxjs/toolkit'
import uiReducer from './ui/ui.slice'
export default configureStore({
reducer: {
ui: uiReducer,
}
})
Create your theme map
// themes.scss
$themes: (
light: (
bg: #f5fcff,
fg: #002433,
),
dark: (
bg: #004966,
fg: #f5fcff,
),
);
Create the themify @mixin
// themify.scss
@import 'themes';
@mixin themify($property, $key, $themes: $themes) {
// Iterate over the themes
@each $theme, $colors in $themes {
// Create a selector
&.#{$theme}-theme,
.#{$theme}-theme & {
// Output the declaration
#{$property}: map-get($colors, $key);
}
}
}
Create the layout component
// layout.jsx
import { useSelector, useDispatch } from "react-redux";
import { toggleTheme } from "../../store/ui/ui.slice";
import './layout.scss';
export default function Layout(props) {
const theme = useSelector(state => state.ui);
const dispatch = useDispatch();
return (
<>
<header className={`${theme} container`}>
<Header />
<button onClick={() => dispatch(toggleTheme())}>Toggle Theme</button>
</header>
<div className={`${theme} container`}>
{props.children}
</div>
</>
)
}
Apply styles to the layout
// layout.scss
@import "../../assets/style/themify";
header {
@include themify('background', 'body-bg');
}
Now create your pages
// home.jsx
import { Layout } from "../../components/layout/layout";
export default function Home() {
return (
<Layout>
<section>
Home Page
</section>
</Layout>
)
}
// about.jsx
import { Layout } from "../../components/layout/layout";
export default function About() {
return (
<Layout>
<section>
About Page
</section>
</Layout>
)
}
Create routes for the application
// App.js
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Home from './pages/home/home';
import About from './pages/about/about';
function App() {
return (
<Router>
<Switch>
<Route exact path='/' component={Home} />
<Route exact path='/tasks' component={About} />
</Switch>
</Router>
);
}
export default App;
The output:
Run the output on codepen.
Thanks.
Top comments (0)