Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[utils] Server side rendering #6068

Closed
kybarg opened this issue Feb 6, 2017 · 29 comments
Closed

[utils] Server side rendering #6068

kybarg opened this issue Feb 6, 2017 · 29 comments
Labels
new feature New feature or request

Comments

@kybarg
Copy link
Contributor

kybarg commented Feb 6, 2017

Problem description

Server side rendering breaks when using withWidth util as we have in /material-ui/utils/withWidth.js:

if (width === null) {
  return null;
}

Need to have ability to pass width when rendering on server or set width depending on userAgent.

Versions

  • Material-UI: next
  • React: 15.4.2
  • Browser: Chrome 56
@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 6, 2017

That's a known limitation of this Higher-order Component.
That logic was introduced with #5405 to address other issues.
Our only hope is HTTP Client Hints but they aren't implemented yet.

@oliviertassinari
Copy link
Member

Oh, are you saying you want to change the component to accept a width property?
I'm not sure what would be the use case for this Higher-order Component then.

@kybarg
Copy link
Contributor Author

kybarg commented Feb 6, 2017

@oliviertassinari Yes exactly. I want to be able to set width manually depending on user agent for example. I need at least to know approximate screen size.

@oliviertassinari
Copy link
Member

oliviertassinari commented Feb 6, 2017

In that case, we would accept a PR to override the inner state 👍 .

@oliviertassinari oliviertassinari added the new feature New feature or request label Jul 4, 2017
@rsaccon
Copy link

rsaccon commented Jul 5, 2017

I just ran into this issue (I think). When attempting to use withWidth, serverside rendering silently just produces an empty node, resp. HTML comment node:

<!-- react-empty: 1 -->

is there any recommended work-around to deal with this, while this issue is open ?

@oliviertassinari
Copy link
Member

oliviertassinari commented Jul 5, 2017

The recommended workaround would be, do not use that util. It really depends on the situation. The best situation is when you can use CSS media queries. This issue is kept open as looking for work-around. So your question have all his place here. So far, we have:

  • use CSS media query when possible. Support should be already pretty good here. If not let us know where you struggle.
  • add the ability to provide our own width from the outside for SSR, you can already do it but that requires boilerplate on userland. I guess that having a initalWidth property could help. I think that it should be into the [xs,..., lg] space.
  • last question at stake, should the approximation suggested by @kybarg be included into Material-UI? We could expose a default helper function when relying on the user agent. The utils would take a platform as input like desktop, mobile or tablet and output a width into the [xs,..., lg] space.

@rsaccon
Copy link

rsaccon commented Jul 5, 2017

ok, thanks. Another option might be responsive-redux, which has option to provide default values for server side rendering.

oliviertassinari added a commit that referenced this issue Jul 5, 2017
Some side though on this new property.
People using it should have some mechanism so that the property stay the same
between the server side rendering and the client side rendering.

Closes #6068
@sebastienfi
Copy link

@oliviertassinari A few month have passed, what would be the workaround of choice nowadays ?

@kybarg
Copy link
Contributor Author

kybarg commented Mar 19, 2018

@sebastienfi In my project I use express-device and set initialWidth depending on device type

@kleyson
Copy link
Contributor

kleyson commented Jun 11, 2018

@oliviertassinari Hi, any chance on getting the initialWidth from the theme?

render() {
      const { initialWidth, theme, width, ...other } = this.props;
      const props = {
        width: width || this.state.width || initialWidth || initialWidthOption || theme.initialWidth,
        ...other,
      };

It will help to not being passing the initialWidth to every component as props, or do something else ugly to handle this configuration globally. Any drawbacks on this approach?
Sorry if I'm saying something stupid, I don't have a big understanding about material-ui.

@oliviertassinari
Copy link
Member

@kleyson Yes, we could pull the value out of the theme. I'm not sure about theme.initialWidth specifically, but that can work.

@kleyson
Copy link
Contributor

kleyson commented Jun 11, 2018

@oliviertassinari Thanks for the quick answer!! Can you point me a direction? I can do the PR with the code/test/docs if that can help.

@oliviertassinari
Copy link
Member

oliviertassinari commented Jun 11, 2018

@kleyson What do you think of using theme.props.MuiWithWidth.initialWidth for consistency?
Yes, a pull-request is welcome :).

@n-sviridenko
Copy link

@oliviertassinari any plans/news about this feature? We have components we use in many places and it's very painful to always set initialWidth

@oliviertassinari
Copy link
Member

@n-sviridenko It's already live.

@n-sviridenko
Copy link

@oliviertassinari weird, since which version?

@oliviertassinari
Copy link
Member

@n-sviridenko #11831

@amankapoor

This comment has been minimized.

@amankapoor
Copy link

Hi, my comment was marked resolved. So, is this comment the answer to my question? #6068 (comment)

@smhindex
Copy link

Hi, no better solution yet ?

@oliviertassinari
Copy link
Member

@smhindex
Copy link

Thanks for fast reply!
This also happens on <Hidden> component on server-side rendering, the section will shown in browser but result an empty node in page-source, if we remove the <Hidden>, the node will be filled!

@oliviertassinari
Copy link
Member

@sm-hashemi You can use the CSS implementation of the Hidden component: https://material-ui.com/layout/hidden/#css.

@smhindex
Copy link

@oliviertassinari Thanks!

I have <Hidden mdUp> for Mobile and <Hidden smDown> for Desktop

  1. tried implementation="css":
    works to populate node element in page-source, but also caused mismatched class names and corrupted some other elements style!
  2. tried initialWidth:
    At the first load, Mobile section is shown and a few moments later Mobile section hide and Desktop section shown. how to resolve this?

@oliviertassinari
Copy link
Member

  1. It's not normal! It should be working. I would dig here.

@junibrosas
Copy link

I moved from using withWidth HOC to useMediaQuery hook + withTheme.

@oliviertassinari
Copy link
Member

@junibrosas Did you try this API?

import useMediaQuery from '@material-ui/core/useMediaQuery';

function MyComponent() {
  const matches = useMediaQuery(theme => theme.breakpoints.up('sm'));

  return <span>{`theme.breakpoints.up('sm') matches: ${matches}`}</span>;
}

https://material-ui.com/components/use-media-query/#using-material-uis-breakpoint-helpers

@junibrosas
Copy link

@oliviertassinari yes, and I am using MUI 3.9.3 so this is how I import it:

import { unstable_useMediaQuery as useMediaQuery } from '@material-ui/core/useMediaQuery';

@Guneetgstar
Copy link

withWidth in nextjs disables SSR at all. See (vercel/next.js#18872).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new feature New feature or request
Projects
None yet
Development

No branches or pull requests

10 participants