Closed DrianHillman closed 5 years ago
Hey, thank you for the bug report. I'm not sure it's my responsibility to make the library SSR safe.
Did you try importing medium-zoom
conditionally? Something along those lines:
const mediumZoom =
typeof window !== 'undefined' ? require('medium-zoom').default : () => {}
Edit: see recommended solution.
Hey @francoischalifour, thanks for pinging me back! I think we're on the right track and a solution like this would work. So far so good in my tests, but does the api then change in any way if using a require
?
I've had to use mediumZoom.default('img.class')
to get the function to fire. But when it does execute it's having difficulty closing & not functioning smoothly.
Here's a quick deploy to a Demo Page to see the difficulty it has opening & closing. Very strange! 🌀
import React from 'react';
import { graphql } from 'gatsby';
import styled from 'styled-components';
var mediumZoom = Function.prototype;
if (typeof window !== 'undefined') {
mediumZoom = require('medium-zoom');
}
//...
export default class Template extends React.Component {
componentDidMount() {
console.log(mediumZoom.default); // {1}
try {
mediumZoom.default(document.querySelectorAll('.zoomable img'), {
scrollOffset: 0,
margin: 48,
background: '#081c48dd',
});
} catch (e) {
console.log("Couldn't execute from ComponentDidMount:", e);
}
}
render() {
const { data } = this.props;
const { markdownRemark } = data; // data.markdownRemark holds our post data
const { frontmatter, html } = markdownRemark;
return (
<>
<Main>
<div className='portfolio-post'>
<h1>{frontmatter.title}</h1>
<Content dangerouslySetInnerHTML={{ __html: html }} /> // {2}
</div>
</Main>
<Footer />
</>
);
}
}
// {2} Markdown Content
### Demo
<div class="img-gallery zoomable">
<img src="ex-image-1.jpg" alt="Photo" title="Photo">
<img src="ex-image-2.jpg" alt="Photo" title="Photo">
<img src="ex-image-3.jpg" alt="Photo" title="Photo">
<img src="ex-image-4.jpg" alt="Photo" title="Photo">
<img src="ex-image-5.jpg" alt="Photo" title="Photo">
<img src="ex-image-6.jpg" alt="Photo" title="Photo">
<img src="ex-image-7.jpg" alt="Photo" title="Photo">
<img src="ex-image-8.jpg" alt="Photo" title="Photo">
<img src="ex-image-9.jpg" alt="Photo" title="Photo">
</div>
{1}
console.log(mediumZoom)
screenshot showing mediumZoom is a Module with a default function
Indeed, I made a mistake in the code snippet (I updated it). When using require
, you need to access the library with default
. You can then use mediumZoom
as usual.
Note that your images are heavy – the browser seems to struggle a bit on first load. I would recommend cropping them a little bit and compressing them. If you want to reduce the latency at first zoom, you can preload the images.
I gave it a try @DrianHillman and my recommendation would be to use a dynamic import:
class Template extends React.Component {
zoom = null
componentDidMount() {
import('medium-zoom').then(mediumZoom => {
this.zoom = mediumZoom.default('.zoomable img')
})
}
componentWillUnmount() {
if (this.zoom) {
this.zoom.detach()
}
}
}
🎉 This is now working beautifully, François — thanks for helping troubleshoot! @francoischalifour
Bug description
👋🏽Hello! I've included this library as part of a Gatsby & React project, however my build fails when I import this package.
Step 1 of the Usage section is a simple
import mediumZoom from 'medium-zoom'
. When I add this import to the top of my JS file my build fails with the following response:It looks like this is a common error where there's no
window
server-side but this package's code is being run & flagged by Webpack. Is there any way around this?Gatsby has the following page with some possible leads to a solution— Debugging HTML Builds
How to reproduce
medium-zoom
per the docsmediumZoom(selector, options)
call to ComponentDidMount (after the image elements are rendered)gatsby build
to generate a production buildExpected behavior
The build should complete to deploy!
Environment
medium-zoom
version: Latest