react-native-calendars icon indicating copy to clipboard operation
react-native-calendars copied to clipboard

Changing theme dynamically

Open jondesam opened this issue 5 years ago • 13 comments

is there any way to change theme dynamically depends on state or props?

I found #322 but still wonder any other possible ways to change theme dynamically

jondesam avatar Nov 08 '19 19:11 jondesam

Maybe anyone has an idea how to work around that issue? I have failed miserably few times with different approaches (not involving source editing).

Unfortunately react-native-calendars is now the only one package which stops our app new release introducing Dark Mode support on iOS.

Also could an owner or contributor tell us how much effort and/or how difficult it will be to introduce dynamic styles? I'm open to help with development during next weekend if you're interested.

Simek avatar Nov 14 '19 17:11 Simek

Having the same problem. It's a slight hack but I solved the problem by setting the key prop based on the theme i.e

const [{key, theme}, setTheme] = useState({key: 'dark', theme: {...}})
...
<Calendar key={key} theme={theme} />

When the theme changes, so does the key, so the Calendar rerenders only when the theme changes.

reubn avatar Feb 05 '20 17:02 reubn

Having the same problem. It's a slight hack but I solved the problem by setting the key prop based on the theme i.e

const [{key, theme}, setTheme] = useState({key: 'dark', theme: {...}})
...
<Calendar key={key} theme={theme} />

When the theme changes, so does the key, so the Calendar rerenders only when the theme changes.

Yes, but it will re-render the calendar. As the styles are constructed in the constructor you can't change the theme.

I had achieved this by making changes in style creation

https://drive.google.com/open?id=1mZOVjOjuQdiesgnzvkxQXPd5LUpIFkkW

amol251 avatar Mar 04 '20 08:03 amol251

What exactly did you change?

reubn avatar Mar 04 '20 08:03 reubn

you can use this code

https://drive.google.com/open?id=1FRwJGiv-9_yNIutnqJ8ZLMb3ZzKIih2Y

run the example.

amol251 avatar Mar 05 '20 04:03 amol251

@amol251, your link does not work :(

eqlion avatar Apr 06 '20 22:04 eqlion

@amol251 Can your share your changes

narender2031 avatar Apr 08 '20 21:04 narender2031

Link: https://drive.google.com/open?id=1FRwJGiv-9_yNIutnqJ8ZLMb3ZzKIih2Y

This link is working, check this code

amol251 avatar Apr 17 '20 03:04 amol251

Do you have any idea how we can support it? @ethanshar @emilisb

chenei avatar Jun 03 '20 18:06 chenei

It's a little problematic. The way the Calendar component was designed is so the theme prop is more of an initialTheme prop. It is being used only when the component constructed. This making it an un-controlled component (theme wise)

One solution is to use key (as already suggested here). But since Calendar is a huge component it can heavily affect on performance.

Using getDerivedStateFromProps is impossible, because we're keeping the generated style as a class member (on this) and getDerivedStateFromProps is a static method.

The only right solution is to turn this prop (theme) to a controlled prop. But unfortunately, this requires a lot of work and possibly introduce breaking changes.

ethanshar avatar Jun 07 '20 06:06 ethanshar

thanks a lot, @amol251!

Btw, I don't think that useState is a good way to solve this problem if someone is needed to pass more than two params, here's my solution:


const keyRender = (selectedDate: Date, theme: string) => {
        const date = dateFormatter(selectedDate) // '2012-02-02'
        return `${date}-${theme}` 
    }


<Calendar
      key={keyRender(selectedDate,theme)}
/>

glushkina1 avatar Jul 22 '22 19:07 glushkina1

I will leave here the full copy-paste solution for dark mode, using the approach from the first post:

const themes = {
  light: {
    calendarBackground: 'white',
    dayTextColor: 'black',
    monthTextColor: 'black',
    textDisabledColor: 'grey',
  },
  dark: {
    calendarBackground: 'black',
    dayTextColor: 'white',
    monthTextColor: 'white',
    textDisabledColor: 'grey',
  }
};
    const {colorScheme} = useColorScheme();
    const [{key, theme}, setTheme] = useState({key: colorScheme, theme: themes[colorScheme]});
    useEffect(() => {
       setTheme({key: colorScheme, theme: themes[colorScheme]});
     }, [colorScheme]);

return (
        <Calendar
          key={key}
          theme={theme}
...

manueldeprada avatar Mar 04 '24 14:03 manueldeprada