Warning: React attempted to reuse markup in a container but the checksum was invalid. This generally means that you are using server rendering and the markup generated on the server was not what the client was expecting. React injected new markup to compensate which works but you have lost many of the benefits of server rendering. Instead, figure out why the markup being generated is different on the client or server:
(client) ="slick-slide slick-cloned Testimony__Te
(server) ="slick-slide slick-active slick-cloned
I was having the same issue and have found that it comes from using the responsive property. If the current breakpoint doesn't match what's assigned to the slidesToShow property (the one that determines how many images are rendered on the server), you get the checksum mismatch. Since there's no easy way for the server to know the client's breakpoint (and therefore how many to render), ideally I think the client should at first respect the slidesToShow setting and then update it to the correct breakpoint on componentDidMount.
You can pretty easily do this yourself manually. Here's a bit of code that works for me. I'm taking the trouble to render a few slides on the server, but you could easily just render and empty string. Basically the script lazy updates the slider when the component mounts and sets the right number of images.
EDIT: this code is bad. See below...
class FeaturedTattoos extends React.Component {
constructor(props) {
super(props);
this.state = {
clientRendered: false,
};
}
componentDidMount() {
if (isClient) this.setState({ clientRendered: true });
}
renderTattoos(tattoos, slidesToShow, server) {
if (server && tattoos.length !== slidesToShow) tattoos.splice(slidesToShow);
return tattoos.map((tattoo) => {
return (
<div key={tattoo.filename}>
<img
src={`/tatteasyTattoos/${tattoo.filename}`}
alt={tattoo.filename}
style={{ maxHeight: '165px', height: 'auto' }}
/>
<div className={style.getTattooButton}>
<button className="btn btn-secondary btn-sm">Get Tattoo</button>
</div>
</div>
);
});
}
render() {
const settings = {
dots: false,
infinite: true,
speed: 500,
slidesToShow: 4,
slidesToScroll: 1,
lazyLoad: false,
arrows: true,
responsive: [
{ breakpoint: 550, settings: { slidesToShow: 1 } },
{ breakpoint: 750, settings: { slidesToShow: 2 } },
{ breakpoint: 1000, settings: { slidesToShow: 3 } },
{ breakpoint: 1600, settings: { slidesToShow: 4 } },
{ breakpoint: 2000, settings: { slidesToShow: 5 } },
{ breakpoint: 100000, settings: { slidesToShow: 6 } },
],
prevArrow: <LeftArrow />,
nextArrow: <RightArrow />,
};
const tattoos = this.props.featuredTattoos.images;
return (
<Slider {...settings} tattoos={tattoos}>
{ this.state.clientRendered
? tattoos.length
? this.renderTattoos(tattoos, settings.slidesToShow)
: <div><img src="https://via.placeholder.com/165x165?text=No+Tattoos" alt="" /></div>
: tattoos.length
? this.renderTattoos(tattoos, settings.slidesToShow, true)
: <div>No featured tattoos.</div>
}
</Slider>
);
}
}
export default FeaturedTattoos;
Unfortunately, the above code isn't quite right. The client/server code matched only when the client break point matches the slidesToShow setting. Then I tried lazy adding the responsive property, which avoided the checksum problems but the responsive part wouldn't instantiate because it's triggered by ComponentWillMount.
Anyway, I was spending too much time on it so I gave up trying to render it at all on the server. The return of my render function is now:
return (
<div>
{ this.state.clientRendered
? (
<Slider {...settings} tattoos={tattoos}>
{ tattoos.length
? this.renderTattoos(tattoos)
: <div><img src="https://via.placeholder.com/165x165?text=No+Tattoos" alt="" /></div>
}
</Slider>
)
: null
}
</div>
);
And it works like a charm, except no server rendering. If anyone else knows how to server render this with breakpoints and without checksum errors, I'd be curious how to do it. I think a good solution would be to have a new option for server rendering, where the responsive feature fired on ComponentDidMount instead of ComponentWIllMount. That way the responsive property could be omitted at first then added after a first render. A think a little risk of FOUC is the best trade off for server rendering.
Thank you @unleashit for the insight, I second having a server rendering option and set slick-active on componentDidMount, so we can just render all the slide in server side and then when client loads it will decide which slides should shown. Then we can just inline the slides and overflow it to avoid breaking the layout, so we get server rendering with acceptable styling.
Agree with above. I happen to have some server side client detection which attempts to guess at the breakpoint, but there is no way to tell react-slick which breakpoint to render on the server. So ideally I think there would be an optional prop for which breakpoint to use during server-side render, and then code in componentDidMount that will correct it on the client if the guess was wrong.
Put in a pull request to fix this issue and do what I said above. @akiran can you take a look?
No such issue currently occurs with server-side rendering. Please feel free to request reopen if disagree.
I had this problem.
My fix:
Move component to const sliderShow =
Use componentDidMount for set true
componentDidMount() {
this.setState({
activeSlide: true,
});
}
@laveesingh Such an error does occur.
How can the server possibly know what responsive breakpoint to use? Slick can only get this information when the client render takes over. I am facing this problem and I am sure others are too. In future, if you are not willing to help diagnose the issue, the least you can do is leave it open for others to assist.
@nickspiel I have been using a fork with the code from my PR in order to solve this problem, but sadly it is so far behind master now that I can't really recommend you use it. The only workaround seems to be to just skip rendering the slider on the server but that has the unfortunate consequence that the images will not start to load until after the JS is loaded which is not ideal for many scenarios.
Yeah, that is what I was thinking too. Unfortunately, in my case, we have a requirement for this content to be rendered serverside for SEO purposes.
I have decided to go with a predominantly CSS solution (no longer us react-slick) with a little JS just for the interactions.
Most helpful comment
Thank you @unleashit for the insight, I second having a server rendering option and set
slick-activeon componentDidMount, so we can just render all the slide in server side and then when client loads it will decide which slides should shown. Then we can just inline the slides and overflow it to avoid breaking the layout, so we get server rendering with acceptable styling.