The problem:
I'm using react-slick in conjunction with react-preload-image (latest versions on both) to create a page with multiple slider rails. The idea is to show my portfolio by category, so I'm listing out each category using react-slick to display images and react-preload-image to show the preload image and then the portfolio image.
The good news is that as long as I don't resize the browser window, it looks great and does exactly what I want it to. The bad news, is that when I resize down my browser window (decrease width) the app completely crashes - blank screen, lots of ugly messages in my console, as follows:
Uncaught TypeError: Cannot set property 'onload' of undefined
at PreloadImage.componentWillUnmount (index.js:66)
at callComponentWillUnmountWithTimer (react-dom.development.js:19866)
at HTMLUnknownElement.callCallback (react-dom.development.js:347)
at Object.invokeGuardedCallbackDev (react-dom.development.js:397)
at invokeGuardedCallback (react-dom.development.js:454)
at safelyCallComponentWillUnmount (react-dom.development.js:19873)
at commitUnmount (react-dom.development.js:20293)
at commitNestedUnmounts (react-dom.development.js:20349)
at unmountHostComponents (react-dom.development.js:20645)
The problem appears to be happening with react-preload-image. I get one of these entries per image (so 40 images, 40 of these warnings).
I've refactored this in several different ways to try to work around this, all to no avail. Here are my components and their code:
PortCatRails.js - creates all the rails
return (
<div>
{
portcats.map((cat) => {
return (
<PortfolioRail key={uuid()} title={cat.name} catId={cat.id} />
)
})
}
</div>
);
PortfolioRail.js - creates each rail using react-slick
class PortfolioRail extends React.Component {
constructor(props) {
super(props)
}
render() {
const portItems = this.props.portfolio.filter((item) => {
return (item.portcats && item.portcats.indexOf(this.props.catId+'') !== -1)
})
const settings = {
dots: false,
className: "center",
centerPadding: "80px",
infinite: true,
speed: 500,
slidesToScroll: 1,
centerMode: false,
ladyLoad: true,
slidesToShow: 5,
responsive: [
{
breakpoint: 576,
settings: {
slidesToShow: 1,
slidesToScroll: 1,
arrows: false,
swipeToSlide: true,
centerMode: true
}
},
{
breakpoint: 768,
settings: {
slidesToShow: 2,
slidesToScroll: 1,
arrows: false,
swipeToSlide: true,
centerMode: true
}
},
{
breakpoint: 992,
settings: {
slidesToShow: 3,
slidesToScroll: 1,
arrows: true,
centerMode: false
}
},
{
breakpoint: 1900,
settings: {
slidesToShow: 4,
slidesToScroll: 1,
arrows: true,
swipeToSlide: false,
centerMode: false
}
}
]
};
return (
portItems.length > 0 &&
<div>
<h4>{this.props.title}</h4>
<Slider {...settings}>
{portItems.map((item) => {
return (
<PortRailItem data={item} key={uuid()} />
)
})}
</Slider>
</div>
)
}
}
PortfolioRailItem.js - One Component Per Portfolio Item in a rail
const PortRailItem = (props) => {
const {projectTitle, shortDesc, propcats, previewImg} = props.data;
const [infoClass, setInfoClass] = useState('');
const handleMouseEnter = (e) => {
setInfoClass('railItem__info--expanded');
}
const handleMouseLeave = (e) => {
setInfoClass('');
}
return (
<div>
<div className="railItem__outer" onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave}>
<div className="railItem__inner">
<ImageWithPreloader src={previewImg} className="railitem__img-preloader" />
<div className={`railItem__info ${infoClass}`}>
<h5>{projectTitle}</h5>
<div className={`railItem__info--short-desc ${infoClass}`}>
{shortDesc}
</div>
</div>
</div>
</div>
</div>
)
}
ImageWithPreloader.js - displays the given image with a preloader
const ImageWithPreloader = (props) => {
const {src, className = 'img-peloader', duration = '1000ms' } = props;
return (
<PreloadImage
src={src}
className={className}
duration={duration}
lazy
/>
)
}
ONE FINAL CLUE: As I said, I only get the error when downsizing the browser window, and ONLY when it hits one of the breakpoints in the settings, so it's no coincidence. I'm just not sure how to handle it at this point.
If anybody has seen something like this, I'd love to know the fix for it. This is the only image preloader that I like so far (and I've tried several).
Thanks!
So I don't know if this problem is unique to my implementation, but I found a fix for it. Apparently there's a bit of a bug in the react-preload-image, but it's a super-easy one-line fix.
On line 66 of the index.js file, simply change this:
PreloadImage.prototype.componentWillUnmount = function componentWillUnmount() {
if (this.observer) this.observer.disconnect();
this.preloader.onload = null;
};
to this:
PreloadImage.prototype.componentWillUnmount = function componentWillUnmount() {
if (this.observer) this.observer.disconnect();
// just add an if(this.preloader) to the next line and all is well
if(this.preloader) this.preloader.onload = null;
};
And the plugin works great. I've let the author know, hopefully he'll have this implemented in his next release.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.