Created
December 14, 2021 13:37
-
-
Save imabp/f063a6af6bfba8d96a92c8de757ab9b6 to your computer and use it in GitHub Desktop.
useStoryblok hook for Typescript developers. Implements the Declaration Merging and type support.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import StoryblokClient, { StoryData } from 'storyblok-js-client' | |
import { useState, useEffect } from 'react' | |
// Addition by Github: imabp: | |
// The following code implements Declaration merging which helps to fulfill the requirement for useStoryblok hook in a typesafe way. | |
declare global { | |
interface Window{ | |
StoryblokBridge: FunctionConstructor | |
} | |
interface Function{ | |
on:Function | |
} | |
} | |
///////////// | |
//instantiating the StoryblokClient | |
const Storyblok = new StoryblokClient({ | |
accessToken: process.env.STORYBLOK_ACCESS_TOKEN, | |
cache: { | |
type: 'memory', | |
clear: 'auto' | |
} | |
}) | |
export const useStoryblok = (originalStory: StoryData, preview: boolean) => { | |
const [story, setStory] = useState(originalStory); | |
const initEventListeners = () =>{ | |
const {StoryblokBridge} = window; | |
if (typeof StoryblokBridge !== "undefined") { | |
// initialize the bridge with your token | |
const storyblokInstance = new StoryblokBridge(); | |
// reload on Next.js page on save or publish event in the Visual Editor | |
storyblokInstance.on(["change", "published"], () => | |
location.reload() | |
); | |
// live update the story on input events | |
storyblokInstance.on("input", ( event:any) => { | |
// check if the ids of the event and the passed story match | |
if (story && event.story.content._uid === story.content._uid) { | |
// change the story content through the setStory function | |
setStory(event.story); | |
} | |
}); | |
storyblokInstance.on("enterEditmode", (event:any) => { | |
// loading the draft version on initial enter of editor | |
Storyblok.get(`cdn/stories/${event.storyId}`, { | |
version: "draft", | |
}) | |
.then(({ data }) => { | |
if (data.story) { | |
setStory(data.story); | |
} | |
}) | |
.catch((error) => { | |
console.log(error); | |
}); | |
}); | |
} | |
} | |
const addBridge = (cb: VoidFunction) => { | |
const existingScript = document.getElementById('storyblokBridge') | |
if (!existingScript) { | |
const script = document.createElement('script'); | |
script.src = "//app.storyblok.com/f/storyblok-v2-latest.js" | |
script.id = "storyblokBridge" | |
document.body.appendChild(script); | |
script.onload = () => { | |
cb(); | |
} | |
} | |
else { | |
cb(); | |
} | |
} | |
useEffect(() => { | |
// only load inside preview mode | |
if (preview) { | |
// first load the bridge, then initialize the event listeners | |
addBridge(initEventListeners); | |
} | |
}, [originalStory, preview, setStory]); // runs the effect only once & defines effect dependencies | |
useEffect(() => { | |
setStory(originalStory); | |
}, [originalStory]); | |
return story; | |
} | |
export default Storyblok; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment