moved global state loic to separate file
- moved related types and interfaces too
This commit is contained in:
parent
1e645a14ca
commit
9861aeda7f
4 changed files with 95 additions and 30 deletions
29
src/App.tsx
29
src/App.tsx
|
@ -1,12 +1,9 @@
|
|||
import { useEffect, useState } from "react"
|
||||
import { useContext, useEffect, useState } from "react"
|
||||
import { Routes, Route } from "react-router-dom"
|
||||
import styled, { ThemeProvider } from "styled-components"
|
||||
import { Helmet } from "react-helmet-async"
|
||||
import storage from "local-storage-fallback"
|
||||
import { isIE } from "react-device-detect"
|
||||
|
||||
import { ThemeType } from "../types/styled-components"
|
||||
|
||||
import Loading from "./components/Loading"
|
||||
import Navbar from "./components/Navbar"
|
||||
import Footer from "./components/Footer"
|
||||
|
@ -20,6 +17,8 @@ import Portfolio from "./pages/Portfolio"
|
|||
import theming from "./styles/theming"
|
||||
import GlobalStyle from "./styles/globalStyle"
|
||||
|
||||
import { ActionsEnum, globalContext } from "./globalContext"
|
||||
|
||||
const IENotSupported = styled.p`
|
||||
margin: auto;
|
||||
font-size: 2rem;
|
||||
|
@ -34,17 +33,12 @@ const StyledContentContainer = styled.div`
|
|||
margin-top: 5rem;
|
||||
`
|
||||
|
||||
const App = () => {
|
||||
export default function App() {
|
||||
const { globalState, dispatch } = useContext(globalContext)
|
||||
const [isLoading, setIsLoading] = useState(true)
|
||||
const [currentTheme, setCurrentTheme] = useState<ThemeType>(
|
||||
(storage.getItem("theme") || "dark") as ThemeType // get theme from storage and set to "dark" mode if not set already
|
||||
)
|
||||
|
||||
// set loading to false if all fonts are loaded
|
||||
useEffect(() => {
|
||||
// show loading screen until all fonts are loaded.
|
||||
// Experimental feature. Not fully supported on all browsers (IE, I'm looking at you).
|
||||
// https://developer.mozilla.org/en-US/docs/Web/API/FontFaceSet
|
||||
|
||||
// checks if document.fonts.onloadingdone is supported on the browser
|
||||
if (typeof document.fonts.onloadingdone != undefined) {
|
||||
document.fonts.onloadingdone = () => {
|
||||
|
@ -55,11 +49,6 @@ const App = () => {
|
|||
}
|
||||
}, [])
|
||||
|
||||
useEffect(() => {
|
||||
// save theme when it is changed
|
||||
storage.setItem("theme", currentTheme)
|
||||
}, [currentTheme])
|
||||
|
||||
if (isIE)
|
||||
return (
|
||||
<IENotSupported>
|
||||
|
@ -70,9 +59,9 @@ const App = () => {
|
|||
return (
|
||||
<ThemeProvider
|
||||
theme={{
|
||||
currentTheme: currentTheme,
|
||||
currentTheme: globalState.theme,
|
||||
setTheme(setThemeTo) {
|
||||
setCurrentTheme(setThemeTo)
|
||||
dispatch({ type: ActionsEnum.UPDATE_THEME, payload: setThemeTo })
|
||||
},
|
||||
}}
|
||||
>
|
||||
|
@ -104,5 +93,3 @@ const App = () => {
|
|||
</ThemeProvider>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
|
|
76
src/globalContext.tsx
Normal file
76
src/globalContext.tsx
Normal file
|
@ -0,0 +1,76 @@
|
|||
import { createContext, useEffect, useReducer } from "react"
|
||||
import storage from "local-storage-fallback"
|
||||
|
||||
import type { Dispatch, ReactNode, ReactElement } from "react"
|
||||
|
||||
export type SiteLocale = "en" | "kr"
|
||||
export type SiteTheme = "dark" | "light"
|
||||
|
||||
export enum ActionsEnum {
|
||||
UPDATE_THEME,
|
||||
UPDATE_LOCALE,
|
||||
}
|
||||
|
||||
export interface IGlobalState {
|
||||
locale: SiteLocale
|
||||
theme: SiteTheme
|
||||
}
|
||||
|
||||
export type GlobalAction =
|
||||
| {
|
||||
type: ActionsEnum.UPDATE_THEME
|
||||
payload: SiteTheme
|
||||
}
|
||||
| {
|
||||
type: ActionsEnum.UPDATE_LOCALE
|
||||
payload: SiteLocale
|
||||
}
|
||||
|
||||
export interface IGlobalContext {
|
||||
globalState: IGlobalState
|
||||
dispatch: Dispatch<GlobalAction>
|
||||
}
|
||||
|
||||
const defaultState: IGlobalState = {
|
||||
locale: (storage.getItem("locale") || "en") as SiteLocale,
|
||||
theme: (storage.getItem("theme") || "dark") as SiteTheme,
|
||||
}
|
||||
|
||||
export const globalContext = createContext({} as IGlobalContext)
|
||||
|
||||
function reducer(state = defaultState, action: GlobalAction): IGlobalState {
|
||||
switch (action.type) {
|
||||
case ActionsEnum.UPDATE_THEME:
|
||||
state.theme = action.payload
|
||||
break
|
||||
|
||||
case ActionsEnum.UPDATE_LOCALE:
|
||||
state.locale = action.payload
|
||||
break
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
||||
return { ...state }
|
||||
}
|
||||
|
||||
export function GlobalStore(props: { children: ReactNode }): ReactElement {
|
||||
const [globalState, dispatch] = useReducer(reducer, defaultState)
|
||||
|
||||
// save theme when it is changed
|
||||
useEffect(() => {
|
||||
storage.setItem("theme", globalState.theme)
|
||||
}, [globalState.theme])
|
||||
|
||||
// save locale when it is changed
|
||||
useEffect(() => {
|
||||
storage.setItem("locale", globalState.locale)
|
||||
}, [globalState.locale])
|
||||
|
||||
return (
|
||||
<globalContext.Provider value={{ globalState, dispatch }}>
|
||||
{props.children}
|
||||
</globalContext.Provider>
|
||||
)
|
||||
}
|
|
@ -2,16 +2,19 @@ import React from "react"
|
|||
import ReactDOM from "react-dom"
|
||||
import { HelmetProvider } from "react-helmet-async"
|
||||
import { BrowserRouter } from "react-router-dom"
|
||||
import { GlobalStore } from "./globalContext"
|
||||
|
||||
import App from "./App"
|
||||
|
||||
ReactDOM.render(
|
||||
<React.StrictMode>
|
||||
<GlobalStore>
|
||||
<BrowserRouter>
|
||||
<HelmetProvider>
|
||||
<App />
|
||||
</HelmetProvider>
|
||||
</BrowserRouter>
|
||||
</GlobalStore>
|
||||
</React.StrictMode>,
|
||||
document.getElementById("root")
|
||||
)
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
import "styled-components"
|
||||
|
||||
export type ThemeType = "dark" | "light"
|
||||
import type { SiteTheme } from "../src/globalContext"
|
||||
|
||||
declare module "styled-components" {
|
||||
export interface DefaultTheme {
|
||||
currentTheme: ThemeType
|
||||
setTheme(setThemeTo: ThemeType): void
|
||||
currentTheme: SiteTheme
|
||||
setTheme(setThemeTo: SiteTheme): void
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue