Hi,
How can I use the window object inside a theme? for example window.matchMedia
thx
You need to take into account that the code is going to be excuted in both Node and the browser, and in Node window
is not avaible.
What it’s usually done is something like this:
const API = typeof window !== 'undefined' ? window.API: NodeAlternative;
For most of the things, there is usually a npm package. For example, our @frontity/wp-source
is using "cross-fetch"
to import either the browser fetch
or a Node alternative that implements the same API.
import fetch from 'cross-fetch';
It works great
In case of media queries, you also need to consider that Node doesn’t know the screen size but it needs to generate an HTML anyway.
The only information Node has from the browser is the UserAgent, which doesn’t include screen size. Besides, if you want to cache that HTML in a CDN to serve it faster (and you should do that), it can’t use the UserAgent because the same HTML is served by the CDN to all the users.
So, for example, if you want to know if the screen is bigger than 600px you do this:
const MyComp = () => {
const bigger = window.matchMedia('(max-width: 600px)');
return (
<div>{bigger ? "bigger" : "smaller"}</div>
);
};
But you need to supply a default value in Node:
const MyComp = () => {
const bigger = typeof window !== "undefined"
? window.matchMedia('(max-width: 600px)');
: true; // Assume screen is bigger than 600px in Node (SSR)
return (
<div>{bigger ? "bigger" : "smaller"}</div>
);
};
Node will generate this HTML:
<div>bigger</div>
If a device with a screen smaller than 600px displays this HTML, it will display "bigger"
at first, then when React loads and evaluates window.matchMedia
, it will be changed to "smaller"
leading to a bad user expirience.
So depending on what you want to do, sometimes it may not be a good idea to mix media queries with server side rendering.
What do you want to do by the way?
Thanks Luis, I was building a sidebar but this can be useful in many cases.
I’m building my personal blog and frontity is really powerful, as soon as I publish it I share it here to receive feedback
Awesome. Looking forward to see your work