Incorporating React State into CSS Styles

Currently, I am immersed in a project based on NextJS where I have to utilize React State to determine the width of a div. In the existing setup, this calculation takes place within a .tsx file using constants and is incremented upon clicking a button. The resulting width is then transmitted as a prop to the component.

At present, I am employing inline styling to specify the width of the div. However, I am intrigued to find out if it is feasible to directly pass the prop into the .module.css file I'm utilizing, as it would result in a neater and more convenient approach for implementing media queries later on. Is this achievable?

Furthermore, is there a way to import variables from the media queries back into the .tsx file?

Main File:

const [width, setWidth] = React.useState(0)
const increment: number = maxWidthTop / totalRounds

export default function Labeller() {
  function clicked() {
    setWidth(width + increment)
  }
  return (
        <Progress
            width={width} />
  )}

Component File:

import styles from '../../styles/Progress.module.css'

type ProgressProps = {
    width: number;
}

export default function ProgressBar(props: ProgressProps) {
    return (
        <div className={styles.main}>
            <div className={styles.bar}>
                <div className={styles.base}></div>
                <div style={{width: `${props.width}em`}} className={styles.top}></div>
            </div>
        </div>
    )
}

Answer №1

When it comes to dynamically modifying the css module at runtime, it's important to note that the css files are handled separately from the javascript in the browser, making it challenging to update styles on the fly. Using inline styles for setting width is a viable option, although managing media queries can be tricky as you rightly pointed out.

An alternative approach could involve creating a function that generates a css string incorporating your width variable and then injecting this output into a style element:

import "./styles.css";

const divWidthStyles = (width: number) => `
  .${styles.top} {
    width: ${width}px;
  }

  @media only screen and (min-width: 600px) {
    .${styles.top} {
      width: ${2 * width}px;
    }
`;

...

export default function ProgressBar(props: ProgressProps) {
  return (
   <div className={styles.main}>
       
       {/* Use style element */}
       <style>{divWidthStyles(props.width)}</style>

       <div className={styles.bar}>
         <div className={styles.base}></div>
         <div className={styles.top}></div>
       </div>
     </div>;
}

Another technique involves leveraging css variables in conjunction with JavaScript to update the width property when changes occur, utilizing useEffect(). Here's an example:

function ProgressBar(props: ProgressProps) {
 const { width } = props;

 const divRef = useRef<HTMLDivElement | null>(null);

 useEffect(() => {
   if (divRef.current) {
     divRef.current.style.setProperty("--width", `${width}px`);
   }
 }, [width]);

 return (
   ...
     <div
       className={"dynamic_width"}
       ref={(ref) => (divRef.current = ref)}
     ></div>
   ...
 );
}

You can then reference this variable within your css.module file like so:

.dynamic_width {
 height: 200px;
 background: red;
 width: var(--width);
}

@media only screen and (min-width: 600px) {
.dynamic_width {
 width: calc(2 * var(--width));
}
}

As a side note, consider exploring styled-components, a library designed to simplify styling components with ease. It offers a clean and efficient solution that may enhance the overall aesthetics of your project.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for retaining directories in build when running npm run build

I have a unique setup for my SPA react app where each personal project is stored as a directory with normal index.html, .js, and .css files, while the layout is created with react. Currently, I am facing an issue where I am unable to use <Link> to r ...

Adding -moz & -o prefixes to code that only has -webkit tags can be done by manually duplicating each line of

Imagine having a webpage located at this link: After saving the page and running the HTML file on my localhost, everything seems to work smoothly in Chrome due to the presence of -webkit prefixes in the CSS. Now the question arises - how can I ensure that ...

Introduce new router events, routeChangeStart and routeChangeComplete, within the client-side components of next js 14

I am currently working on a Next.js v14.0.4 project and I am facing an issue with implementing a top loader progress bar using the NProgress package for route changes triggered by Link or router.push(). The handleRouteChangeStart and handleRouteChangeCom ...

The function makeStyle does not support the use of "this" keyword

My goal is to create a dynamic background image based on my props. I attempted to accomplish this by creating a React style and setting it to the picture stored in my state, but for some reason I am unable to use this.state.pictures. I'm not sure why. ...

Encountered an unusual IP address while attempting to start yarn - EADDRNOTAVAIL

Recently, I installed OpenSUSE on my laptop and decided to try out a new React application. However, when I ran the commands from the create-react-app site: npx create-react-app my-app cd my-app yarn start I encountered an issue in my terminal with the f ...

The function window.require does not exist

Here is the code I wrote: const { ipcRenderer } = window.require('electron'); An error occurred: TypeError: window.require is not a function I attempted to utilize IPC communication in order to manage the Electron window using React. Regrett ...

The never-ending loading problem at the bottom of the Firefox screen seems

I am facing an issue while trying to open something in Firefox using window.open(). The loading screen seems to never stop, and I cannot pinpoint the reason behind it. Any advice on how to resolve this would be greatly appreciated. View Screenshot: This ...

When I hover over my images, they begin to flash before my eyes

My layout is set up so that when I hover over the printer image, it should switch to another image. However, instead of smoothly transitioning, the image starts to flash. This issue occurs in all browsers, indicating that I have made a mistake somewhere. ...

ZeroClipboard intricate CSS issue

I have a list of images with an option box that appears on mouseover. The box contains an embedded code input field for copying purposes. I recently implemented zeroclipboard to enable the copy function on click. However, when I hover over an image and try ...

Deciphering the principles of Bootstrap

I'm looking to understand more about what Bootstrap is. I know it's commonly used for styling web pages, but could you provide me with a clear explanation? Can big companies like Twitter, Facebook, or YouTube utilize Bootstrap for their platforms ...

Why is React JS unable to discover my exported modules?

Upon running my React app, the console displayed the following error message: Failed to compile. ./src/components/login/index.js Attempted import error: 'Login' is not exported from './login'. Here is an overview of the folder struct ...

Encountering a Module not found error with a ValidationError when trying to import an SVG file within a React

I've set up a manual Webpack 5 configuration for my React project with TypeScript. I am facing an issue while trying to import an SVG icon and using Material UI in the project. The error message I'm encountering is: Module not found: ValidationEr ...

Upon commencing the project, an error arises with reactstrap when attempting to import the library

Issue with Error console in node_modules/reactstrap/lib/index.js: SyntaxError: Cannot use import statement outside a module at internalCompileFunction (node:internal/vm:73:18) at wrapSafe (node:internal/modules/cjs/loader:1176:20) ... Node.js v18. ...

JSX tags without any inner content should be self-closed

After successfully running this code, I encountered an issue when committing it to git. The error message 'ERROR: src/layouts/index.tsx:25:9 - JSX elements with no children must be self-closing' appeared. I attempted to resolve the error by addi ...

What is the best way to include additional items in a list?

Trying to add a new element of an array to the list while updating one property (id) by making it 1 more than the length of the array has resulted in strange outputs. Each new object added causes all elements to have values of array.length + 1. Various at ...

Looking for a feature similar to mix-blend-mode that can change the text color to its inverse when overlapping with a background color that matches

Seeking assistance on a Mondrian-style CSS Grid layout with a rotated sticky heading. Looking to achieve a visual effect where intersecting text turns white when a black horizontal line passes over or under it. https://i.sstatic.net/YQaxV.png Considering ...

css table cells with overflow

I need help with a table where I have text in one of the td cells that goes beyond the right border and wraps to the next line. What I want is for the overflowing text to be hidden when it reaches the border, showing only the last 3 visible characters repl ...

How to Delete an Added Image from a Dialog Title in jQuery

I've tried multiple solutions from various sources, but I'm still struggling to remove an image from a dialog. Whenever I attempt to do so, I end up with multiple images instead of just one. It's important to note that I only want the image ...

Shifting an image within a div using HTML5 and CSS3

I am wondering how to position the image 50px from the top and 50px from the left within the div. Should I use padding for this? <header> <img src="logo.png" alt="" /> </header> header { width... height: background: (url) } ...

Create a basic grid layout using Bootstrap

I'm struggling to create this straightforward grid layout using Bootstrap: https://i.sstatic.net/fnQRt.png Essentially, I attempted the following method based on Bootstrap documentation: <td> <div class="row"> <div class=&q ...