React Splide with Gatsby: Top Tip
Tags: gatsby, react, javascript, tutorial
Published: 2021-01-07 18:40:29

**Update: Splide is now in Version 3 and (since the update) [React Splide](https://github.com/Splidejs/react-splide) appears to work well with Gatsby (tested on V4) without any additional configuration. This article is only useful to those using an older version of React Splide**.

---

If you have never come across SplideJS then I encourage you to check it out. It's a great plugin for building carousels and I think the documentation is brilliant. [Check out SplideJS here](http://splidejs.com/).

Let me start by telling you about my painful afternoon...

Today, I have been working on a website for a client using Gatsby. Until today, everything has been going great! My task today was to develop a carousel component, so I turned to my favourite tool (Splide) and I noticed they have a React port. "Awesome" I thought, "This is going to be simple!".

Then I noticed an error in the Netlify logs.


```
  14 | 	else
  15 | 		root["Splide"] = factory();
> 16 | })(self, function() {
     |  ^
  17 | return /******/ (() => { // webpackBootstrap
  18 | /******/ 	"use strict";
  19 | /******/ 	var __webpack_modules__ = ({


  WebpackError: ReferenceError: self is not defined
```

This doesn't look good.

## Debugging Gatsby HTML Builds

There's a great section in the Gatsby documentation about debugging HTML builds [here](https://www.gatsbyjs.com/docs/debugging-html-builds/). I consulted this and found the section on third-party modules. I have used this approach with other packages that expect the `window` object during the HTML build, so I thought I would give this a go.

In `gatsby-node.js` I added the following:

```js
exports.onCreateWebpackConfig = ({ stage, loaders, actions }) => {
  // With SSR enabled during development, we capture this
  // in development and during production build.
  if (stage === "build-html" || stage === "develop-html") {
    actions.setWebpackConfig({
      module: {
        rules: [
          {
            test: /@splidejs/,
            use: loaders.null(),
          },
        ],
      },
    })
  }
}
```

Great 💥 let's run `gatsby build` again...oh dear

```
Error: Minified React error #130; visit https://reactjs.org/docs/error-decoder.html?invariant=130&args[]=undefined&args[]= for the full message or use the non-minified dev environment for full errors and additional helpful warnings.
```

We have a new error. A new error is good, it means progress! If we copy the error decoder URL into a new browser we can see that React returned the following error.

```
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined.
```

At first I was puzzled, but after a coffee it made sense. We have told webpack to replace React Splide with a dummy module. The `loaders.null()` suggests that we're not going to return anything valuable - it's `undefined`.

So the end result for my carousel component was this:

```jsx
export const Testimonials = ({ data }) => {
  if (typeof window === "undefined") {
    return <p>Server Render</p>
  }

  return (
    <Box mb={24}>
      <Splide
        options={{
          perPage: 1,
          perMove: 1,
          arrows: false,
        }}
      >
        {data.map(testimonial => {
          return (
            <SplideSlide key={testimonial.id}>
              <Flex bgColor="blue.600">
                <Box width="400px">
                  {/* To be replaced with Gatsby Image */}
                  <img src={testimonial.imageUrl} alt={testimonial.alt} />
                </Box>
                <Box py={12} px={12} display="flex" flex={1} color="white">
                  <PortableText blocks={testimonial._rawTestimonialText} />
                </Box>
              </Flex>
            </SplideSlide>
          )
        })}
      </Splide>
    </Box>
  )
}
```

This means that when the HTML build takes place, the component will return `<p>Server Render</p>` rather than `undefined`. If we run the code in the browser, `window` is defined and we will see the Splide component.

## Conclusion

I wrote this with the hope that it will help anyone else who comes across this problem. If you found it useful then let me know in the comments.

Thanks!