I'm trying to ensure my menu items are mounted in the DOM for SEO purposes. I'm using a MUI Select component for a dropdown nav and am passing in keepMounted props which are ultimately spread on the Popper component via MenuProps.
I can see the menu items HTML (ul > li) mounted in my inspector but when I inspect source or CURL they don't exist.
const TopicSelect = ({
classes,
width,
selectClassName,
topicData,
selectedValue,
onChange,
}) => {
const isMobile = isWidthDown('xs', width)
return (
<FormControl data-testid="TopicSelect-formControl" variant="filled">
<InputLabel className={classes.label} htmlFor="topic-select-input">
Filter by topic
</InputLabel>
<Select
data-testid="TopicSelect-select"
className={classnames(classes.select, selectClassName)}
onChange={onChange}
value={selectedValue}
autoWidth
native={isWidthDown('xs', width) ? true : false}
input={
<FilledInput
name="topic"
id="topic-select-input"
className={classes.filledInput}
disableUnderline
/>
}
MenuProps={{
style: {
zIndex: 1500,
},
keepMounted: true,
}}
>
{isMobile
? [
<option value="" />,
topicData.map(topic => (
<option
key={`${topic.text}-LearnNav-menuItem`}
value={topic.path}
>
{topic.text}
</option>
)),
]
: [
<MenuItem key="none" value="">
<em>None</em>
</MenuItem>,
topicData.map(topic => (
<MenuItem
key={`${topic.text}-LearnNav-menuItem`}
value={topic.path}
>
{topic.text}
</MenuItem>
)),
]}
</Select>
</FormControl>
)
}
I would expect the menu items HTML to be rendered to the DOM because that's what the prop is intended to do. Not sure why they're not rendered during SSR.
Has anyone encountered this problem before? Is there a way to make sure these items are mounted that I'm overlooking?
The discussions I have seen regarding the keepMounted prop on Menu have been related to accessibility rather than SEO/SSR (though I see now that the prop description on Modal mentions SEO). For the accessibility use cases, a slight delay on the rendering of the menu items (rather than being part of the initial rendering) will not cause any issues.
The delay is due to Portal (Menu uses Popover which uses Modal which uses Portal) triggering the rendering of its children via an effect.
The only way I see to work around this is to leverage the disablePortal prop (in addition to keepMounted) on Menu/Popover/Modal/Portal.
<Select
value={state.age}
onChange={handleChange}
inputProps={{
name: "age",
id: "age-simple"
}}
MenuProps={{ keepMounted: true, disablePortal: true }}
>
<MenuItem value="">
<em>None</em>
</MenuItem>
<MenuItem value={10}>Ten</MenuItem>
<MenuItem value={20}>Twenty</MenuItem>
<MenuItem value={30}>Thirty</MenuItem>
</Select>
I don't use SSR myself and haven't tested this solution in an SSR environment, but I believe it should do the trick.
Code resources:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With