Adjust properties based on screen size with server-side rendering compatibility

I'm currently using the alpha branch of material-ui@v5.

At the moment, I have developed a custom Timeline component that functions like this:

const CustomTimeline = () => {
  const mdDown = useMediaQuery(theme => theme.breakpoints.down("md"));

  return (
    <Timeline position={mdDown ? "right" : "alternate"}>
      {/* some children */}
    </Timeline>
  );
};

Although it works mostly as intended, mobile users might encounter layout shifts due to the fact that useMediaQuery relies on JavaScript and is only executed client-side. I am searching for a CSS-based solution that can be used with Server-Side Rendering (SSR).

One potential approach I've considered is:

const CustomTimeline = () => {

  return (
    <Fragment>
      <Timeline sx={{ display: { xs: "block", md: "none" } }} position="right">
        {/* some children */}
      </Timeline>
      <Timeline sx={{ display: { xs: "none", md: "block" } }} position="alternate">
        {/* some children */}
      </Timeline>
    </Fragment>
  );
};

This solution should work because the sx prop gets converted into emotion styling and gets included in the HTML file. However, this method will increase the size of the DOM. Are there any better alternatives to achieve the same result?

Answer №1

I encountered a similar issue in the past while utilizing Next.js for SSR, however, the solution is not dependent on that.

Start by installing this package and importing it into your root file, such as App.js

import mediaQuery from 'css-mediaquery';

Next, create a function to pass ThemeProvider of material-ui

const ssrMatchMedia = useCallback(
        (query) => {
            const deviceType = parser(userAgent).device.type || 'desktop';
            return {
                matches: mediaQuery.match(query, {
                    width: deviceType === 'mobile' ? '0px' : '1024px'
                })
            };
        },
        [userAgent]
);

Make sure to provide the userAgent!

Then, include ssrMatchMedia in MuiUseMediaQuery

<ThemeProvider
    theme={{
        ...theme,
        props: {
            ...theme.props,
            MuiUseMediaQuery: {
                ssrMatchMedia
            }
        }
    }}>

This approach should function correctly. I am utilizing an older version of material-UI instead of v5. The name MuiUseMediaQuery might be different, but this method has been effective for me thus far. Feel free to inform me if you encounter any issues.

Answer №2

In order to prevent the initial rendering before useMediaQuery is launched, it is recommended to follow the advice from the Reactjs documentation. One option is to move that logic to useEffect if it is not essential for the first render. Another approach is to delay displaying that component until after the client renders, especially if the HTML appears broken until useLayoutEffect runs.

To avoid including a component that relies on layout effects in the server-rendered HTML, you can conditionally render it using showChild && and defer its display with useEffect(() => { setShowChild(true); }, []). By doing this, the UI will not appear broken before hydration.

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

difficulty receiving the information promptly via an AJAX request (utilizing AJAX and the 'for' loop)

Currently, I am successfully retrieving data from an ajax call for individuals. However, my next task is to retrieve multiple sets of data simultaneously. Here is the code snippet: for(var i = 1; i <= 2; i++){ console.log(i); $.ajax({ url: cal ...

Attention: Two children with identical keys were found, ""

In my current project, I am utilizing ReactJS, NextJS 14, Tailwind CSS, and Framer Motion. When working with React, it's essential to assign unique keys to each repeated child component. In my case, this requirement carries over to NextJS as well. To ...

What causes the website to malfunction when I refresh the page?

I utilized a Fuse template to construct my angular project. However, upon reloading the page, I encountered broken website elements. The error message displayed is as follows: Server Error 404 - File or directory not found. The resource you are looking fo ...

Tips for determining if an item in one array is present in a different array

Looking for a way to disable a button using React code? Take a look at the snippet below: todos.filter(todo => todo.completed === true) .map(todo => todo.id) .includes(this.state.checkedIds) But there's a catch - it always seems to return ...

Problem with AngularJS factory causing issues with promises

I have a factory in AngularJS set up like this: 'use strict'; angular.module('frontRplApp') .factory('paymentService', function ($rootScope, $http, config, tools) { var urlBase = config.baseUrl; var payme ...

What is the best way to display the Link above my custom component?

How can I ensure that the Link appears above the component I created in Next.js 11 version? I encountered this error message: Warning: Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()? ...

What is the best way to address Peer dependency alerts within npm?

Here is a sample package.json that I am using for my application: dependencies : { P1 : “^1.0.0” // with peer dependency of p3 v1 P2 : “^1.0.0” // with peer dependency of p3 v2 } P1 and P2 both have peer dependencies on ...

What is the best way to test a React component that includes a Router, Redux, and two Higher Order Components using Jest and Enzyme?

I'm currently facing a challenge with this issue. I have a React Component that is linked to React Router 4 and Redux store, and it's wrapped by two HOCs. It may sound complicated, but that's how it was implemented. Here's the export st ...

JavaScript string representing the actual value of a string

In order to reliably extract string literals from a JavaScript string, I need to create a function, let's name it f. Here are some examples: f('hello world') //-> 'hello world' (or "hello world") f('hello "world"') / ...

React with embedded maps

Incorporated Google Maps into my React project, but encountered an error message stating that the page cannot load Google Maps correctly due to ownership issues. After researching, I discovered that I need to enable billing for my account in order to use ...

In AngularJS, the $http get method is displaying the status code of the data object instead of

After pondering over this issue for several days, I am still unable to pinpoint what I am doing wrong. Any suggestions or insights would be greatly appreciated. My challenge lies in trying to showcase the response from a rest service to the user by utilizi ...

Is there a performance benefit to using node.js over client-side JavaScript in comparison to Chrome/V8?

Currently, I am working on a client-side javascript application for image manipulation. However, some of the operations are running quite slowly in the browser, taking about 2-3 seconds to complete. To address this issue, I am considering implementing a s ...

Tips for displaying HTML content in each step using React and material-ui stepper

I'm curious if it's possible to display HTML content instead of just text in the examples of Stepper. When I tried putting HTML inside <StepContent />, the page ended up looking strange: https://i.stack.imgur.com/Or31r.png Here is the cod ...

Timeout for AngularJS Bootstrap UI Modal

I am having some trouble with opening a bootstrap modal using the $timeout function. The issue I am facing is that the modal keeps opening multiple times as the timeout fires repeatedly. Any assistance or suggestions on how to resolve this problem would be ...

I need to figure out how to add a key to my div element in React using Promises

I am diving into React js for the first time and venturing on a small project. I am eager to learn how to assign a key to each image within my div element. How can I efficiently accomplish this task? class Image extends Component { constructor( ...

Can you provide the date time format used in the JSTL fmt tag?

To display date and time in JSTL, the fmt tag can be utilized. Details can be found here In order to format the date for use with front end tools like the datatable, a specific date format needs to be specified. By using parameters such as type or dateSty ...

The server is indicating that the validation for the user has failed due to the required field "foo" not being provided in the Node.js

An error message was received with the following details: "User validation failed: email: Path email is required., display_name: Path display_name is required." The error name returned is: ValidationError. The AJAX call code snippet is as follows: f ...

What is the method for transferring the value of a jQuery variable to a PHP variable without using AJAX?

Here is my JavaScript code: $('#affiliates_name').change(function(){ var id = $('#affiliates_name').val(); }); Below is the corresponding HTML: <select id="affiliates_name" style="display: none;" name="affiliates_name"> < ...

Optimizing the usage of override Button with Box component in Material-UI

Recently, I've been delving into the Box component in material-UI (https://material-ui.com/components/box/#box) and attempting to understand and write code for it. Specifically, I've been experimenting with overriding a Button component using th ...

Tips for customizing a single row in v-data-table? [Vuetify]

My goal is to change the background color of a specific row that contains an entry matching the value of lowestEntry. <v-col cols="8"> <v-data-table :loading="loadEntryTable" loading-text="Searching for data..." ...