#javascript #reactjs #next.js #storyblok
Вопрос:
У меня есть страница верхнего уровня, для которой я использую 95% контента на /[...slug].js
CMS без головы, поэтому мне не нужно создавать отдельные папки для маршрутов.
У меня есть содержимое в структурах папок в CMS, таких как /holidays/railways
и /holidays/cruising
, и на переднем конце я могу получить к нему доступ как есть, все хорошо.
Однако при размещении следующей ссылки JS и маршрутизатора на этих страницах и при нажатии на них URL-адрес в конечном итоге обновится, но содержимое останется прежним.
Я пробовал делать:
<NextLink href="/[...slug]" as="/holidays/cruising">
Destinations test
</NextLink>
и URL — адрес есть сейчас /holidays/cruising
, но контент все еще /holidays/railways
есть-кто-нибудь сталкивался с этой проблемой раньше?
У меня было искушение создать holidays
папку на следующих страницах JS и поместить [slug].js
ее, но я не хочу пробовать, если это не сработает.
Вот моя /[...slug].js
страница
import Head from "next/head";
import Storyblok, { useStoryblok } from "lib/storyblok";
import Components from "components";
import ThemeProvider from "ThemeProvider";
const Slug = ({ page, preview }) => {
let story = useStoryblok(page, preview);
return (
<ThemeProvider>
<Head>
<title>Page</title>
</Head>
<Components {...story.content} key={story.content._uid} />
</ThemeProvider>
);
};
export default Slug;
export async function getStaticProps({ params = {}, preview }) {
let slug = params.slug ? params.slug.join("/") : "home";
let sbParams = {
version: "published",
cv: "",
resolve_relations: ""
};
if (preview) {
sbParams.version = "draft";
sbParams.cv = Date.now();
}
const { data } = await Storyblok.get(`cdn/stories/${slug}`, sbParams);
let props = {
page: data.story || {},
preview: preview || false
};
return {
props,
revalidate: 60
};
}
export async function getStaticPaths() {
let { data } = await Storyblok.get("cdn/links/");
let paths = [];
Object.keys(data.links).forEach(link => {
if (data.links[link].is_folder || data.links[link].slug === "home") return;
paths.push({ params: { slug: data.links[link].slug.split("/") } });
});
return {
paths,
fallback: "blocking"
};
}
storyblok.js
import { useEffect, useState } from "react";
import StoryblokClient from "storyblok-js-client";
const Storyblok = new StoryblokClient({
accessToken: process.env.STORYBLOK_API_KEY,
cache: {
clear: "auto",
type: "memory"
}
});
export function useStoryblok(originalStory, preview) {
let [story, setStory] = useState(originalStory);
// adds the events for updating the visual editor
// see https://www.storyblok.com/docs/guide/essentials/visual-editor#initializing-the-storyblok-js-bridge
function 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(true)
);
// live update the story on input events
storyblokInstance.on("input", event => {
if (story amp;amp; event.story.content._uid === story.content._uid) {
setStory(event.story);
}
});
storyblokInstance.on("enterEditmode", event => {
// 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);
});
});
}
}
// appends the bridge script tag to our document
// see https://www.storyblok.com/docs/guide/essentials/visual-editor#installing-the-storyblok-js-bridge
function addBridge(callback) {
// check if the script is already present
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 = () => {
// once the scrip is loaded, init the event listeners
callback();
};
} else {
callback();
}
}
useEffect(() => {
// only load inside preview mode
if (preview) {
// first load the bridge, then initialize the event listeners
addBridge(initEventListeners);
}
}, [initEventListeners, preview]);
return story;
}
export default Storyblok;
Заранее спасибо
Комментарии:
1. Если вы измените свою ссылку на
<NextLink href="/holidays/cruising">
, это что-нибудь изменит?2. К сожалению, нет — я нажимаю на свой сервер vercel, чтобы узнать, не является ли это проблемой локального сервера
3. Изменяется ли
story
возвращаемыйuseStoryblok
крючком (на данные новой страницы) при переходе на другую страницу на стороне клиента?4. React будет жаловаться на условное отображение крючка. Возможно, вам придется переместить чек внутрь самого
useStoryblok
крючка.5. @juliomalves да, вы правы — похоже, он работает так, как должен, и я все еще могу войти в режим предварительного просмотра без проблем. Большое вам спасибо за вашу помощь, было приятно иметь возможность взглянуть на это еще одной парой глаз