просто хранишь стейт с выбранной темой в компоненте и вешаешь обработчики для смены стейта
class MyComponent extends Component {
constructor() {
super()
this.state = {
currentTheme: "dark"
}
}
changeTheme(themeName) {
this.setState({
currentTheme: themeName
})
}
render() {
return (
<div>
...
<button onClick={() => this.changeTheme("dark").bind(this)}> {/* байнд для доступа к this внутри ф-и */}
I wanna dark!
}
</button>
<button onClick={() => this.changeTheme("light").bind(this)}>
I wanna light!
</button>
</div>
)
}
}
можешь это все хранить в корневом компоненте, тогда просто вызываешь callback, который дойдет до самого верха и поменяет стейт, а дальше передаешь это как props дочерним компонентам и в зависимости от выбранной темы рендеришь что нужно.
onClick={() => this.props.goDark()} /* например это вызов из ребенка, который очень глубоко */
/* в это уже самый верхний (корневой) компонент */
goDark() { ... }
goLight() { ... }
<RootComponent>
<Child currentTheme={this.state.currentTheme} />
</RootComponent>
можешь это еще дополнительно куда-то в локалсторадж писать и при инициализации читать оттуда.
------------------
ну а по поводу цсс, просто в зависимости от значения в переменной currentTheme - загружаешь нужную css, либо же в самом рендере навешиваешь разные стили/классы
<div className={ this.props.currentTheme === 'dark' ? 'dark-wrapper' : 'light-wrapper' }>
<button className={this.props.currentTheme === 'dark' ? 'btn-primary-yellow' : 'btn-primary-blue' }></button>
</div>