Nikhil Patil
Nikhil Patil

Reputation: 316

How to change a SASS variable value using React Js?

Before making it duplicate question please make sure you read my question

I am asking this question in 2019, Where React Js documentation specify we can use SASS in our react project here's link

I want to switch between light theme and dark theme using dynamic variable which is control by user click

My React Code

import React from 'react';
import './App.scss';

class App extends React.Component {
    render() {
        return (
            <div className="Home">
                I’m slow and smooth
                <button onClick={() => console.log()}>Change theme</button>
            </div>
        );  
    }
}

export default App;

My SASS code:

$theme: light;  // I want to control this variable

$bgcolor: #222222;

@if($theme== light) {
    $bgcolor: white;    
}
@else {
    $bgcolor: black;    
}

.Home {
    background-color: $bgcolor;
    height: 100vh;
}

Upvotes: 4

Views: 5621

Answers (1)

Yuukuari
Yuukuari

Reputation: 135

in case you are still interested, you can kind of change a sass variable by instead using css variables

:root {
    --app-primaryColor: #f49ad1;
    --app-secondaryColor: #211f1e;
}

Then use these variables in your scss files

.button {
    background-color: var(--app-primaryColor);
    color: var(--app-secondaryColor);
}

and update them using React

document.documentElement.style.setProperty('--app-primaryColor', '#ffae00')

Here is a (almost) full example using react and redux. A setTheme action is used to update colors from the document root element. This way you can also configure your theme directly from your react root tag props. These props will be set as the initial state.

// index.html
<div
    id="app"
    primaryColor="red"
    secondaryColor="#f2f2f2"
/>

// css-variables.scss
:root {
    --app-primaryColor: #f49ad1;
    --app-secondaryColor: #211f1e;
}

// app.module.scss
.button {
    background-color: var(--app-primaryColor);
    color: var(--app-secondaryColor);
}

// index.js
import React from 'react'
import ReactDOM from 'react-dom'
import { Provider } from 'react-redux'

import './css-variables'

import App from './app'
import configureStore from './configureStore'

const rootElement = document.getElementById('app')

//Here you could extract your theme variables from your rootElement props and set it as an initial redux state
const initialProps = {}
const store = configureStore(initialProps)

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
rootElement)

// app.js
import React from 'react'
import { connect } from 'react-redux'

import { setTheme } from './actions'
import styles from './app.module'

class App extends React.Component {
    componentDidMount() {
        //In case you have an initial state set from your rootElement
        const { theme, setTheme } = this.props
        setTheme(theme)
    }
    
    generateTheme() {
        const primaryColors = ['#ffae00', '#f49ad1', '#d0666b', '#7c6cd0', '#6cd09d', '#d0ba6c']
        const secondaryColors = ['#4c4c4e', '#2f2f2f', '#dcdcdc', '#fff']

        return {
            primaryColor: primaryColors[Math.floor(Math.random() * primaryColors.length)]
            secondaryColor: secondaryColors[Math.floor(Math.random() * secondaryColors.length)]
        }
    }

    onButtonClick() {
        const theme = this.generateTheme()
        this.props.setTheme(theme)
    }

    render() {
        return (
            <div className="{styles.button}" onClick={this.onButtonClick.bind(this)}>
                Change theme
            </div>
        )
    }
}

const mapStateToProps = (state) => ({
    theme: state.theme,
})

export default connect(mapStateToProps, { setTheme })(App)

// actions.js
export const setTheme = theme => dispatch => {
    //You change your theme vars directly from the root element
    Object.keys(theme)
        .filter(prop => typeof theme[prop] !== 'undefined' && theme[prop] !== null)
        .forEach(prop => document.documentElement.style.setProperty(`--app-${prop}`, theme[prop]))
    
    dispatch({
        type: 'THEME/SET',
        payload: theme
    })
}

Upvotes: 7

Related Questions