次の問題があります。
Jsのcssにgatsby
を使用するemotion
ウェブサイトがあります。私はemotion theming
を使用してダークモードを実装します。ダークモードは、gatsby develop
を実行すると期待どおりに機能しますが、gatsby build && gatsby serve
を使用して実行すると機能しません。より具体的には、ダークモードは、ライトに切り替えて再度切り替えた後にのみ機能します。
私はテーマを処理するトップレベルのコンポーネントに従う必要があります:
const Layout = ({ children }) => {
const [isDark, setIsDark] = useState(() => getInitialIsDark())
useEffect(() => {
if (typeof window !== "undefined") {
console.log("save is dark " + isDark)
window.localStorage.setItem("theming:isDark", isDark.toString())
}
}, [isDark])
return (
<ThemeProvider theme={isDark ? themeDark : themeLight}>
<ThemedLayout setIsDark={() => setIsDark(!isDark)} isDark={isDark}>{children}</ThemedLayout>
</ThemeProvider>
)
}
getInitalIsDark
関数は、localStorage値、OSカラースキームをチェックし、デフォルトはfalseです。アプリケーションを実行してダークモードをアクティブにすると、localStorageの値が設定されます。アプリケーションをリロードすると、getInitialIsDarkメソッドはtrueを返しますが、UIはライトテーマをレンダリングします。明暗の切り替えは期待どおりに機能し、初期ロードだけでは機能しません。
GetInitialIsDarkをtrue
に置き換えると、darkModeのロードは期待どおりに機能しますが、lightModeが壊れます。これを機能させる唯一の方法は、次のコードを使用して時間どおりにロードした後に自動的に再レンダリングすることです。
const Layout = ({ children }) => {
const [isDark, setIsDark] = useState(false)
const [isReady, setIsReady] = useState(false)
useEffect(() => {
if (typeof window !== "undefined" && isReady) {
console.log("save is dark " + isDark)
window.localStorage.setItem("theming:isDark", isDark.toString())
}
}, [isDark, isReady])
useEffect(() => setIsReady(true), [])
useEffect(() => {
const useDark = getInitialIsDark()
console.log("init is dark " + useDark)
setIsDark(useDark)
}, [])
return (
<ThemeProvider theme={isDark ? themeDark : themeLight}>
{isReady ? (<ThemedLayout setIsDark={() => setIsDark(!isDark)} isDark={isDark}>{children}</ThemedLayout>) : <div/>}
</ThemeProvider>
)
}
しかし、これはページの読み込み時に醜いちらつきを引き起こします。
最初のアプローチのフックで何が問題になっていますか?初期値が期待どおりに機能していません。
同様の問題があり、一部のスタイルは、マウント時に設定されたクラスを介して適用されたために有効になりませんでした(プロダクションビルドでのみのように、すべてが開発で正常に機能しました)。
私はハイドレート関数を切り替えることになりましたReactはReactDOM.hydrate
からReactDOM.render
に使用していたため、問題は解消しました。
// gatsby-browser.js
export const replaceHydrateFunction = () => (element, container, callback) => {
ReactDOM.render(element, container, callback);
};
これは私のために働いたものです、これを試して、うまくいったかどうか私に知らせてください。
に src/components / コンポーネントを作成しました navigation.js
export default class Navigation extends Component {
static contextType = ThemeContext // eslint-disable-line
render() {
const theme = this.context
return (
<nav className={'nav scroll' : 'nav'}>
<div className="nav-container">
<button
className="dark-switcher"
onClick={theme.toggleDark}
title="Toggle Dark Mode"
>
</button>
</div>
</nav>
)
}
}
作成した gatsby-browser.js
import React from 'react'
import { ThemeProvider } from './src/context/ThemeContext'
export const wrapRootElement = ({ element }) => <ThemeProvider>{element}</ThemeProvider>
ThemeContext.jsファイルをsrc/context /に作成しました
import React, { Component } from 'react'
const defaultState = {
dark: false,
notFound: false,
toggleDark: () => {},
}
const ThemeContext = React.createContext(defaultState)
class ThemeProvider extends Component {
state = {
dark: false,
notFound: false,
}
componentDidMount() {
const lsDark = JSON.parse(localStorage.getItem('dark'))
if (lsDark) {
this.setState({ dark: lsDark })
}
}
componentDidUpdate(prevState) {
const { dark } = this.state
if (prevState.dark !== dark) {
localStorage.setItem('dark', JSON.stringify(dark))
}
}
toggleDark = () => {
this.setState(prevState => ({ dark: !prevState.dark }))
}
setNotFound = () => {
this.setState({ notFound: true })
}
setFound = () => {
this.setState({ notFound: false })
}
render() {
const { children } = this.props
const { dark, notFound } = this.state
return (
<ThemeContext.Provider
value={{
dark,
notFound,
setFound: this.setFound,
setNotFound: this.setNotFound,
toggleDark: this.toggleDark,
}}
>
{children}
</ThemeContext.Provider>
)
}
}
export default ThemeContext
export { ThemeProvider }
これはあなたのために働くはずです 公式ギャツビーサイト から私が従ったリファレンスです