I want to include Theme UI's presets in my GatsbyJS for switching the mode (dark and light) and the themes.
I can't modify export
of my original code to merge two const
functions into an export
, because export
needs children
to be defined. I will not want to use children
, because another layout file in JSX has already children
. I also can't merge a const
into another const
. You will check the errors at the end. I'll share my repo's small folder at the end for you to test. The In Angular2+ is there any way to extends on inherit const into another const? does not help either.
See my small original code, and notice const
and export
:
import React from 'react'
import {Context} from '../../common'
import SelectLanguage from './SelectLanguage'
import {Links} from './styles'
import {Navegador, StyledHeader} from './styles'
const Header = () => (
<Context.Consumer>
{({ toggleLanguage, lang }) => (
<StyledHeader>
<Navegador id="menu">
<li>
<Links>
{/* ... */}
<SelectLanguage lang={lang} toggleLanguage={toggleLanguage} />
</Links>
</li>
</Navegador>
</StyledHeader>
)}
</Context.Consumer>
)
export default Header
My another small Theme UI code, you can notice const
functions inside the export
:
/** @jsx jsx */
import { jsx, Styled, useColorMode } from 'theme-ui'
import ButtonUI from '../../theme-ui/button-ui'
const themes = ['deep', 'funk', 'future', 'swiss']
const modes = ['default', 'dark']
const getThemeName = (theme) =>
{
switch (theme)
{
case 'deep':
return 'Deep'
case 'funk':
return 'Funk'
case 'future':
return 'Future'
case 'swiss':
return 'Swiss'
default:
return theme
}
}
const getModeName = (mode) =>
{
switch (mode)
{
case 'dark':
return (<span role="img" aria-label="moon"> </span>)
case 'default':
return (<span role="img" aria-label="sun">☀️ </span>)
default:
return mode
}
}
export default function Layout({ children })
{
const [theme, setTheme] = useColorMode()
const [mode, setMode] = useColorMode()
const cycleTheme = (e) =>
{
const i = themes.indexOf(theme)
const next = themes[(i + 1) % themes.length]
setTheme(next)
}
const cycleMode = (e) =>
{
const i = modes.indexOf(mode)
const next = modes[(i + 1) % modes.length]
setMode(next)
}
return (
<Styled.root>
<ButtonUI
sx={{
ml: 2,
}}
onClick={cycleTheme}>
<span role="img" aria-label="theme"> </span>
{getThemeName(theme)}
</ButtonUI>
<ButtonUI
sx={{
ml: 2,
}}
onClick={cycleMode}>
{getModeName(mode)}
</ButtonUI>
</Styled.root>
)
}
Let's merge the second code into the first code, and I renamed const
to function
, since I can not put const
into another const
or modify export
(because children
needs to be defined):
/** @jsx jsx */
import { jsx, Styled, useColorMode } from 'theme-ui'
import {Context} from '../../common'
import SelectLanguage from './SelectLanguage'
import {Links} from './styles'
import {Navegador, StyledHeader} from './styles'
import ButtonUI from '../../theme-ui/button-ui'
const themes = ['deep', 'funk', 'future', 'swiss']
const modes = ['default', 'dark']
const getThemeName = (theme) =>
{
switch (theme)
{
case 'deep':
return 'Deep'
case 'funk':
return 'Funk'
case 'future':
return 'Future'
case 'swiss':
return 'Swiss'
default:
return theme
}
}
const getModeName = (mode) =>
{
switch (mode)
{
case 'dark':
return (<span role="img" aria-label="moon"> </span>)
case 'default':
return (<span role="img" aria-label="sun">☀️ </span>)
default:
return mode
}
}
const [theme, setTheme] = useColorMode();
const [mode, setMode] = useColorMode();
function cycleTheme (e) {
const i = themes.indexOf(theme)
const next = themes[(i + 1) % themes.length]
setTheme(next)
}
function cycleMode (e) {
const i = modes.indexOf(mode)
const next = modes[(i + 1) % modes.length]
setMode(next)
}
function Header () {
return (
<Styled.root>
<Context.Consumer>
{({ toggleLanguage, lang }) => (
<StyledHeader>
<Navegador id="menu">
<li>
<ButtonUI
sx={{
ml: 2,
}}
onClick={cycleTheme}>
<span role="img" aria-label="theme"> </span>
{getThemeName(theme)}
</ButtonUI>
<ButtonUI
sx={{
ml: 2,
}}
onClick={cycleMode}>
{getModeName(mode)}
</ButtonUI>
<Links>
<SelectLanguage lang={lang} toggleLanguage={toggleLanguage} />
</Links>
</li>
</Navegador>
</StyledHeader>
)}
</Context.Consumer>
</Styled.root>
)
}
export default Header
The errors appeared:
Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/warnings/invalid-hook-call-warning.html for tips about how to debug and fix this problem.
resolveDispatcher
node_modules/react/cjs/react.development.js:1465
useContext
node_modules/react/cjs/react.development.js:1473
patch/React$$1.useContext
node_modules/react-hot-loader/dist/react-hot-loader.development.js:2939
useThemeUI
node_modules/@theme-ui/core/dist/index.esm.js:40
useColorMode
node_modules/@theme-ui/color-modes/dist/index.esm.js:169
./src/components/theme/Header/index.jsx/<
src/components/theme/Header/index.jsx:43
40 | }
41 | }
42 |
> 43 | const [theme, setTheme] = useColorMode();
44 | const [mode, setMode] = useColorMode();
45 |
46 | function cycleTheme (e) {
./src/components/theme/Header/index.jsx
You can download small folder of my repo: http://sendanywhe.re/HQ19EMJK or https://filetransfer.io/data-package/i03Or3CD or https://fromsmash.com/Gatsby-i81n-Starter. Use index-example.js
.