Search code examples
cssreactjsstyled-components

setting style values dynamically - react


I need a way to toggle 'flex' to 'none' and vice versa for the following:

const UpdateSampleStyle = makeStyles((theme) => ({
    gridcontainer: {
    display: 'none', //props => props.show,
    justifyContent:'center', 
    marginTop:'5px'
  },
}));


 function UpdateFieldObservations({formdata, handleChangeParent}){
 const show = 'flex';
 const classes = UpdateSampleStyle(show);
const [displaySettings, setDisplaySettings] = useState({
  tradeWaterGrabSample: {display:'flex', justifyContent:'center', marginTop:'5px'},
  tradeWaterCompositeProgram: {display:'flex', justifyContent:'center', marginTop:'5px'},
  soilVapourGrabSample: {display:'flex', justifyContent:'center', marginTop:'5px'},
  soilVapourInsituMeter: {display:'flex', justifyContent:'center', marginTop:'5px'},
  stackEmissionGrabSample: {display:'flex', justifyContent:'center', marginTop:'5px'},
  stackEmissionInsituMeter: {display:'flex', justifyContent:'center', marginTop:'5px'},
  dustDeposition: {display:'none', justifyContent:'center', marginTop:'5px'}
});

}

It is used as follows:

<Grid container spacing={3} style={displaySettings.tradeWaterGrabSample}>
</Grid>
<Grid container spacing={3} style={displaySettings.tradeWaterCompositeProgram}>
</Grid>
<Grid container spacing={3} style={displaySettings.soilVapourGrabSample}>
</Grid>

and so on..

Update: So there were tiny mistakes in my code after I implemented the solution here...that can go unnoticed, adding here for anyone facing the same:

 const classes = UpdateSampleStyle(show);

changed to

 const classes = UpdateSampleStyle({show});

classname changed to className


Solution

  • First of all, this is not the right approach while applying styles.

    Solution 1:

    If you are using plain css, you can keep your styles in separate css files.

    For example,

    .tradeWaterGrabSample {
     // your styles
    }
    .hidden {
      display: none;
    }
    

    Later, in JSX you can put the css classes: For example

    <Grid container spacing={3} className=`tradeWaterGrabSample ${yourCondition ? 'hidden' : ''}`>
    </Grid>
    

    Solution 2:

    You can use classnames / clsx npm library for applying multiple styles: https://www.npmjs.com/package/clsx

    https://www.npmjs.com/package/classnames

    in this case you can easily apply multiple classes based on condition: Eg:

    import classNames from 'classnames';
    ...
    <Grid container spacing={3} className={classNames('tradeWaterGrabSample' , {'hidden': true}> // replace true by your condition
    </Grid>
    

    Solution 3:

    By seeing Grid container I am assuming you are using material-ui / MUI.

    If your using MUI (Aka v5), then you can use sx prop For example,

    <Grid container spacing={3} sx={{
     display: condition ? 'none' : 'flex'
    }}
    justifyContent="center"
    mt="5px"
    >
    </Grid>
    

    For reference:

    https://mui.com/system/the-sx-prop

    https://mui.com/guides/interoperability/

    If your using Material ui (Aka v4), then "sx" prop does not work. you can use makeStyles / withStyles instead.

    References:

    https://v4.mui.com/styles/api/

    https://v4.mui.com/guides/interoperability/

    As you confirmed about material-ui v4

    You can use following:

    const useStyles = makeStyles({
      gridContainer: {
       marginTop: "5px"
      },
      hidden: {
        display: "none"
      },
    });
    

    use following inside component:

    const classes = useStyles(props);
    
    <Grid 
      container 
      spacing={3} 
      justifyContent="center"
      className={classNames(classes.gridContainer, { [classes.hidden]: true } )} // replace true by your condition
    >
    </Grid>
    

    https://v4.mui.com/styles/api/#makestyles-styles-options-hook

    Based on your comment, to use component's props, you can follow this example: https://v4.mui.com/styles/basics/#adapting-based-on-props