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

Selected ListItem styles not working with SSR #492

Closed
dan-kwiat opened this issue Dec 6, 2018 · 10 comments
Closed

Selected ListItem styles not working with SSR #492

dan-kwiat opened this issue Dec 6, 2018 · 10 comments

Comments

@dan-kwiat
Copy link
Contributor

With client-side rendering the first item gets the mdc-list-item--selected class and aria-selected="true" as expected. However with server-side rendering (tested with next.js) this is not the case (and all the items look the same). I believe it's an issue with this library rather than material-components-web?

<List
  singleSelection
  selectedIndex={0}
>
  <ListItem>
    <ListItemText primaryText='One' />
  </ListItem>
  <ListItem>
    <ListItemText primaryText='Two' />
  </ListItem>
  <ListItem>
    <ListItemText primaryText='Three' />
  </ListItem>
</List>
@moog16
Copy link
Contributor

moog16 commented Dec 7, 2018

@dan-kwiat yes from my understanding of how SSR works, I believe the problem is with MDC React and not Web. I'm not super familiar with SSR.

Do you have a test project that I can look at/learn from with the List HTML shown above?

@dan-kwiat
Copy link
Contributor Author

@moog16 to be honest I'm pretty new to SSR as well. This example has a List in the Drawer (see DrawerList.js): https://github.com/dan-kwiat/material-next-template

In development the first item is selected as expected (see screenshot below) and it responds to item clicks. In next's static build however no item is selected (see demo) and handleSelect is never triggered.

screenshot 2018-12-07 at 09 34 57

@moog16
Copy link
Contributor

moog16 commented Dec 7, 2018

I visited your demo https://dan-kwiat.github.io/material-next-template/ and downloaded your project. I noticed that the setSelected method is not being called either, which leads me to believe that your environment isn't properly setup.

In your dev setup, clicking on a list item console.log(), but this does not happen in your live demo.

@dan-kwiat
Copy link
Contributor Author

@moog16 it isn't being called because List's handleSelect method isn't triggered. Setting the state in an explicit click event handler on ListItem works in both cases (see updated demo & code) but the active class still isn't applied.

@moog16
Copy link
Contributor

moog16 commented Dec 11, 2018

@dan-kwiat I looked into this more this afternoon. I think it may have something to do with componentDidMount which is not being called when the site is server rendered. Would you be able to test this? I haven't had time.

@dan-kwiat
Copy link
Contributor Author

dan-kwiat commented Dec 11, 2018

@moog16 componentDidMount is not executed server side but still gets called on first rendering by the client.

I think the problem is the use of child.type.name in @material/react-list. The type name for <ListItem> children is "ListItem" with CSR but "t" with SSR (see console logs in updated demo).

Therefore with SSR renderListItem is never called and none of the event handlers are attached to the List's children. Is there a better way of determining whether a child is a ListItem (and getting its index) - maybe something like getListItemIndex_ in @material/list?

Thanks for your time on this.

@dan-kwiat
Copy link
Contributor Author

dan-kwiat commented Dec 11, 2018

@moog16 so this is a code minification problem, nothing to do with SSR. Same problem with a create-react-app build.

A workaround would be to define the list item type at the top of index.js as:

const ListItemType = (<ListItem/>).type

then replace the condition in renderChild:

if (child.type.name === 'ListItem') {...} // current condition fails with code minification
if (child.type === ListItemType) {...} // this should work

More on element type comparisons here: gaearon/react-hot-loader#304

Edit: comparing to "rendered" element type isn't necessary unless using react-hot-loader

@dan-kwiat
Copy link
Contributor Author

#509

@moog16
Copy link
Contributor

moog16 commented Dec 11, 2018

@dan-kwiat thanks for figuring that out! I spent quite a bit of time and couldn't figure it out. I'll try testing this out with your SSR demo.

@moog16
Copy link
Contributor

moog16 commented Dec 11, 2018

Merged #509...thanks again!

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

No branches or pull requests

2 participants