React / Redux isomorphic / server rendering and media queries

I started creating an isomorphic Noact-based React / Redux application. One of the requirements of the project is the “adaptive” display of specific components based on the “mobile” and “working” views. I implemented the Redux action and the reducer for storing screen information about the user's presentation (based on media queries - "small", "medium", "large") in state. When resizing, the state / storage is updated. The default state is small.

const defaultState = { isMobile: true, isTablet: false, isDesktop: false, sizes: { small: true, medium: false, large: false, huge: false, }, }; 

In a component that should be “responsive” in two different versions based on screen size, I just do:

if (small) return variable1

if (medium) return variable2

All working.

Now I am faced with two problems:

  • my application is isomorphic, this means that the markup also displays the server side. The server does not know anything about user browsers and media queries. Therefore, since my default state is "small", the server will always display "option1". The node server is the entry point for the site. It seems that the rendering should be “delayed” (middleware?), And the server needs to get some information from the client about the width of the browser before the React application gets “delivered”. Any idea how this problem can be solved?

  • because the rendering is based on state, after the “change 1” of the load can always be seen first for a few milliseconds (flicker), even if the size of the browser is “desktop”. This is because JS detection takes a few milliseconds before the state is updated with the current screen width. I think this plays along with the above problem and default state.

I could not find any solution for 1, but I think there should be something isomorphic and responsive / adaptive.

+6
source share
2 answers

You can get the user agent from the header on the server, and then send the reducex action with the information of the user agent with the reducer, which returns the data, so you can determine whether the user on the mobile phone / tablet / desktop / etc and display accordingly

0
source

A very difficult problem, in my opinion, is to solve many of the "dependent" solutions. :)

I am the author of react-sizeme and react-component-queries , two libraries to help with reacting components, and have run into similar problems that you will cover in your question. In my experience, I have found that solving one of your problems often affects the other. I will describe in detail what I mean here, describing my experience below ...

First I tried to solve your "problem 2":

The flickering rendering due to the default state was something I experienced during my initial creation of the react-sizeme . react-sizeme is a higher order component that gets the size available to your component and then passes it to your component. Based on the size, you can, of course, choose different components, as it was in your example, so that a flicker update can happen if you do not get into the sweet state by default. I “conquered” this by modifying react-sizeme to initially make an empty placeholder to get the available width / height, and then only display your component, giving it the “correct” width / height. It is very effective for me. I no longer see the ComponentBob component being displayed, only to unmount it and render ComponentFoo on it immediately.

Then came "Problem 1" ...

react-sizeme began to gain popularity, and in the end I got a library consumer who wanted to use it in the context of server-side rendering. But due to the fix I installed for problem 1, server-side rendering would create a lot of empty content (i.e., Placeholders, which I talked about). After the payload is delivered to the browser, placeholder logic will enter, and eventually the size data will be sent to the component and it will be displayed. This is not ideal, since you, in fact, negate any benefit from performing SSR in the first place. I worked with this user, and we decided that the best way to redirect is to allow react-sizeme to run in "SSR mode". This basically led to discarding the placeholder rendering and allowing the component to display by default so that you don't get blank pages in the original server response, but then you can easily fix the component flicker problem again!

Aaaaaaaaaah! You see what affects here !: (

Thus, basically solving one problem directly affects another.


I continued to give this thought, and I believe that probably the best way to do this is to try to get the width / height of the users browser on the first request. This would essentially mean providing a simple utility that retrieves this information and then sends it back to the server in order to provide an initial user request. You can then use the width / height and pass it through the entire component tree (doing the math along the way) to continue to determine what height / width is available for each component. Super sophisticated stuff here, but may work.

Another danger, of course, is that Google simply indexes a blank page for the initial request (i.e., a blank visualization of a utility that returns the initial width / height). You will need to try to learn some clever HTTP response codes, such as redirects, etc., to ensure that google follows the trail to the appropriate output.


Sorry, this may not be the answer you were looking for, but I hope my experience helps in some way or gives some inspiration. If you come up with interesting experiments, please keep me posted. I would be happy to work with you on this.

+5
source

All Articles