Skip to content

Instantly share code, notes, and snippets.

@jslyonnais
Last active November 21, 2019 16:19
Show Gist options
  • Save jslyonnais/c481c735a7edc95bbcc810f76ddfb80e to your computer and use it in GitHub Desktop.
Save jslyonnais/c481c735a7edc95bbcc810f76ddfb80e to your computer and use it in GitHub Desktop.
Unable preview in Storyblok while using Gatsby & React hooks

Unable preview in Storyblok while using Gatsby & React hooks

  • Install dependencies : gatsby-source-storyblok, storyblok-react, react, gatsby
  • Add Storyblok accessToken in your gatsby-config.js
{
  resolve: 'gatsby-source-storyblok',
  options: {
    homeSlug: 'home',
    version: process.env.BUILD_ENV === 'production' ? 'published' : 'draft',
    accessToken: process.env.BUILD_ENV === 'production'? '000000' : '000000'
  }
},

N.b ReplaceImageUrlBySharpObj will only replace images that are in a field and not into a markdown space. For that, just create another function for that purpose.

import React, { useState, useEffect } from "react"
import { graphql } from 'gatsby'
import Templates from '../templates/templates'
import SbEditable from 'storyblok-react'
import config from '../../gatsby-config'
import { ReplaceImageUrlBySharpObj } from '../config/ReplaceImage'
let sbConfigs = config.plugins.filter((item) => {
return item.resolve === 'gatsby-source-storyblok'
})
let sbConfig = sbConfigs.length > 0 ? sbConfigs[0] : {}
const loadStoryblokBridge = function(cb) {
let script = document.createElement('script')
script.type = 'text/javascript'
script.src = `//app.storyblok.com/f/storyblok-latest.js?t=${sbConfig.options.accessToken}`
script.onload = cb
document.getElementsByTagName('head')[0].appendChild(script)
}
const getParam = function(val) {
var result = ''
var tmp = []
window.location.search
.substr(1)
.split('&')
.forEach(function (item) {
tmp = item.split('=')
if (tmp[0] === val) {
result = decodeURIComponent(tmp[1])
}
})
return result
}
const StoryblokEntry = ({ data }) => {
const [story, setStory] = useState(null)
const [isLoading, setIsLoading] = useState(true)
useEffect(() => loadStoryblokBridge(() => _loadStory({storyId: getParam('path')})), [])
useEffect(() => _initStoryblokEvents())
const _loadStory = (payload) => {
window.storyblok.get({
slug: getParam('path'),
version: 'draft',
resolve_relations: sbConfig.options.resolveRelations || []
}, (res) => {
setIsLoading(false)
setStory(res.story)
})
}
const _initStoryblokEvents = () => {
if(!isLoading) {
let sb = window.storyblok
sb.on(['change', 'published'], (payload) => {
_loadStory(payload)
})
sb.on('input', (payload) => {
if (story && payload.story.id === story.id) {
payload.story.content = sb.addComments(payload.story.content, payload.story.id)
setStory(payload.story)
}
})
sb.pingEditor(() => {
if (sb.inEditor) {
sb.enterEditmode()
}
})
}
}
let pageContext = {
story: (story)? ReplaceImageUrlBySharpObj(story, data.allFile.edges) : null,
globalNav: {
content: {}
}
}
return (story == null) ? <div></div> :
<SbEditable content={story}>
{React.createElement(Templates(story.content.templateKey), {key: story.content._uid, pageContext: pageContext})}
</SbEditable>
}
export const query = graphql`
query {
allFile {
edges {
node {
name
extension
childImageSharp {
fluid(maxWidth: 1920, traceSVG: {color: "#E7E9F7"}) {
tracedSVG
aspectRatio
src
srcSet
srcWebp
srcSetWebp
sizes
}
}
}
}
}
}
`
export default StoryblokEntry
export function ReplaceImageUrlBySharpObj(content, allFile) {
const reg = /"\/\/a.storyblok.com[^,]+/ig
let stringContent = JSON.stringify(content)
let m
while ((m = reg.exec(stringContent)) !== null) {
const url = m[0]
// This is necessary to avoid infinite loops with zero-width matches
if (m.index === reg.lastIndex) {
reg.lastIndex++;
}
const result = _queryImageSharp(url, allFile)
stringContent = stringContent.replace(`${url}`, JSON.stringify(result.childImageSharp.fluid))
}
return JSON.parse(stringContent)
}
function _queryImageSharp(matchUrl, allFile) {
const url = `${matchUrl.replace(/"|\\/g, '')}`
const filename = url.split("/").pop().split('.').slice(0, -1).join('.')
const filter = allFile.filter(file => file.node.name === filename)[0]
return filter.node
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment