【问题标题】:Change GlobalStyles on page load only仅在页面加载时更改 GlobalStyles
【发布时间】:2021-04-29 07:27:18
【问题描述】:

我正在尝试更改body 上的transition,具体取决于页面是否已加载或是否单击了ThemeToggle 按钮。但我看不到向GlobalStyles发送道具的方法

App.tsx

import React, { ReactElement } from 'react'
import { createGlobalStyle } from 'styled-components'
import { Theme } from '@components/Theme/'

interface IPalette {
  body: string
  text: string
}

const GlobalStyles = createGlobalStyle<{ theme: IPalette }>`
  body {
    background: ${({ theme }) => theme.body};
    color: ${({ theme }) => theme.text};
    /* I want to modify the transition on load */
    transition: background-color 0.3s ease;
  }
`

export const App = (): ReactElement => {
  return (
    <Theme>
      <GlobalStyles />
      <h1>Test</h1>
    </Theme>
  )
}

主题.tsx

import React, { FC, useState, useEffect } from 'react'
import { ThemeProvider } from 'styled-components'
import { darkTheme, lightTheme, ThemeToggle } from './theme-style'
import { createCookie, eraseCookie, readCookie } from './cookie'

export const Theme: FC<{children: React.ReactNode}> = ({children}) => {

  const [themeState, setTheme] = useState<boolean>(false)
  const [firstLoad, setFirstLoad] = useState<boolean>(true)

  const changeTheme = (): void => {
    setFirstLoad(false)
    if (themeState) {
      setTheme(false)
      eraseCookie('Theme')
    } else {
      setTheme(true)
      createCookie('Theme', true, 30)
    }
  }
  
  useEffect(() => {
    if (readCookie('Theme')) setTheme(true)
  }, [])

  return (
    <ThemeProvider theme={themeState ? darkTheme : lightTheme}> 
      {children}
      <ThemeToggle theme={themeState} onClick={changeTheme} />
    </ThemeProvider>
  )
}

我正在尝试将 firstLoad 布尔值从 ThemeProvider 发送到 GlobalStyles,但如果我尝试,我会收到来自 TypeScript 的错误。

Type '{ children: (ReactNode | Element)[]; firstLoad: true; theme: IPalette; }' is not assignable to type 'IntrinsicAttributes & IntrinsicClassAttributes<Component<ThemeProviderProps<any, any>, any, any>> & Readonly<...> & Readonly<...>'.

【问题讨论】:

    标签: reactjs typescript styled-components


    【解决方案1】:

    由于这里的目标是仅当用户单击更改主题而不是加载时才能更改body transition,所以我这样做了,它可能不是最好的解决方案,但在尝试了上下文提供程序之后,我认为这是一种不那么复杂的方法,请随时提出替代方案。

    我所做的是将样式化主题转换为返回对象而不是对象字面量的函数,因此我可以传递参数transition 来切换body transition

    app.tsx

    import React, { ReactElement } from 'react'
    import { createGlobalStyle } from 'styled-components'
    import { Theme } from '@components/Theme/'
    
    interface IPalette {
      body: string
      text: string
      transition: string
    }
    
    const GlobalStyles = createGlobalStyle<{ theme: IPalette}>`
      body {
        background: ${({ theme }) => theme.body};
        color: ${({ theme }) => theme.text};
        transition: ${({ theme }) => theme.transition};
      }
    `
    
    export const App = (): ReactElement => {
    
      return (
        <Theme>
          <GlobalStyles />
          <h1>Test</h1>
        </Theme>
      )
    }
    

    主题.tsx

    import React, { FC, useState, useEffect } from 'react'
    import { ThemeProvider, IPalette } from 'styled-components'
    import { ThemeToggle, colors } from './theme-style'
    import { createCookie, eraseCookie, readCookie } from './cookie'
    
    const lightTheme = (transition: boolean): IPalette => ({
      body: colors.bgLight,
      text: colors.textLight,
      transition: transition ? 'background-color 0.3s ease' : ''
    })
    
    const darkTheme = (transition: boolean): IPalette => ({
      body: colors.bgDark,
      text: colors.textDark,
      transition: transition ? 'background-color 0.3s ease' : ''
    })
    
    export const Theme: FC<{children: React.ReactNode}> = ({children}) => {
    
      const [themeState, setTheme] = useState<boolean>(false)
      const [transition, setTransition] = useState<boolean>(false)
    
      const changeTheme = (): void => {
        setTransition(true)
        if (themeState) {
          setTheme(false)
          eraseCookie('Theme')
        } else {
          setTheme(true)
          createCookie('Theme', true, 30)
        }
      }
      
      useEffect((): void => {
        if (readCookie('Theme')) setTheme(true)
      }, [])
    
      return (
        <ThemeProvider theme={themeState ? darkTheme(transition) : lightTheme(transition)}> 
          {children}
          <ThemeToggle theme={themeState} onClick={changeTheme}>
            <span></span>
          </ThemeToggle>
        </ThemeProvider>
      )
    }
    

    【讨论】:

      猜你喜欢
      • 2015-03-27
      • 1970-01-01
      • 2015-03-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-01
      • 1970-01-01
      相关资源
      最近更新 更多