Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
190 views
in Technique[技术] by (71.8m points)

javascript - styled-components change theme dynamically

Is there a way to make styled-components theme adjustable on the fly? For instance, I want the user to be able to change the theme from within the UI and also get theme settings from the API on login. Currently, my theme looks as follows but I would like to change the hardcoded data for variables that I'd be able to set from UI

import { DefaultTheme } from 'styled-components'

export const theme: DefaultTheme = {
  backgroundGradient: 'linear-gradient(to bottom, #f8089c, #e87030)',
  palette: {
    white: '#fff',
    error: '#fa0e15',
    pink: '#fe0582',
  },
  text: {
    main: '#f8089c',
    white: '#fff',
    black: '#000',
  },

  breakpoints: {
    xs: '0px',
    sm: '600px',
    md: '960px',
    lg: '1280px',
    xl: '1920px',
  },
}
question from:https://stackoverflow.com/questions/65882833/styled-components-change-theme-dynamically

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

In order to do this, you want your theme to be stored in a state somewhere such that it can be updated and those updates will trigger re-renders.

We can use two separate context providers: the styled-components ThemeProvider and our own context which will provide some sort of callback which is used to update the theme state.

Here's some sample code which should point you in the right direction.

We create a Context for the theme update function. We give it a default value which logs an error.

const ThemeUpdateContext = createContext(
  (theme: DefaultTheme) => console.error("attempted to set theme outside of a ThemeUpdateContext.Provider")
)

We make a custom theme provider that stores the theme in local state. This wraps its children in providers for both the theme and the update function.

export const MyThemeProvider: React.FC = ({ children }) => {
  // store the entire theme as state, using your constant as the initial state
  const [myTheme, setMyTheme] = useState(theme);

  return (
    <ThemeProvider theme={myTheme}>
      <ThemeUpdateContext.Provider value={setMyTheme}>
        {children}
      </ThemeUpdateContext.Provider>
    </ThemeProvider>
  )
}

We can then use those contexts to make updates from any component inside the MyThemeProvider. You can, for example, push changes to the theme based on a value retrieved from the API or a cookie from localStorage.

Here's a very arbitrary example:

const SampleComponent = () => {
  const updateTheme = useContext(ThemeUpdateContext);
  const currentTheme = useContext(ThemeContext);

  return (
    <button
      onClick={() => updateTheme({
        ...currentTheme,
        text: {
          ...currentTheme.text,
          main: 'blue',
        }
      })}
    >
      Make Main Text Blue
    </button>
  )
}

Typescript Playground Link


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...