I have a component set up like so:

Then I pass it along a fetcher component like so

And it does work with the preview mode, with value taken from my preview slug.
However it does not work when I run the code locally or when deployed at all. I have a react project and my App.tsx looks pretty much copy-and-pasted from the “CatchAllPage” example.
Please help
Hello @future_design, can you set the dynamic value to be $ctx.params.postSlug
?
Yes

This is all fine in the editor. It even loads the correct data
I’m receiving “postSlug” as a props and did register it via plasmic-init
PLASMIC.registerComponent(WordpressPosts, {
name: 'WordpressPosts',
displayName: 'Wordpress Posts',
providesData: true,
importPath: './src/features/wordpress/components',
props: {
children: 'slot',
className: 'string',
language: 'string',
showUntranslatedPosts: 'boolean',
postSlug: 'string',
},
});
It however does not receive it when loading via PlasmicComponent.
It’s just simple with nothing else
Just to simplify the problem I’m just creating a new page with these settings:
And then I have a text which prints that line
But it still doesn’t work.
Right now my work around is to just declare that page using react-router myself but that takes too much time and kinda defeats the purpose of using low-code in the first place
So I managed to get it working. This seems rather hacky and will require the slug set on plasmic editor to has the same name with the slug set in the fetcher component.
I’d love to hear improvements or alternatives or if I’m doing something wrong here
/*
template: /products/[category]/[product]
actualPath: /products/electronics/iphone
returns: { category: 'electronics', product: 'iphone' }
*/
function extractDynamicSegments(template: string, actualPath: string): { [key: string]: string } {
const templateParts = template.split('/');
const actualParts = actualPath.split('/');
const result: { [key: string]: string } = {};
if (templateParts.length !== actualParts.length) {
throw new Error('Template and actual path structures do not match');
}
for (let i = 0; i < templateParts.length; i++) {
const templatePart = templateParts[i];
const actualPart = actualParts[i];
if (templatePart.startsWith('[') && templatePart.endsWith(']')) {
const key = templatePart.slice(1, -1); // Remove brackets
result[key] = actualPart;
} else if (templatePart !== actualPart) {
throw new Error(`Mismatch at segment ${i}: expected "${templatePart}", got "${actualPart}"`);
}
}
return result;
}
// We try loading the Plasmic page for the current route.
// If it doesn't exist, then return "Not found."
export function CatchAllPage() {
const [loading, setLoading] = useState(true);
const [pageData, setPageData] = useState<ComponentRenderData | null>(null);
const [slugsProps, setSlugsProps] = useState<any>(null);
useEffect(() => {
async function load() {
const pageData = await PLASMIC.maybeFetchComponentData(location.pathname);
const pageComponent = pageData?.bundle.components.find((c) => c.isPage);
if (pageComponent && pageComponent.path && location.pathname) {
const slugs = extractDynamicSegments(pageComponent.path, location.pathname);
setSlugsProps(slugs);
}
setPageData(pageData);
setLoading(false);
}
load();
}, []);
if (loading) {
return <div>Loading...</div>;
}
if (!pageData) {
return <div>Not found</div>;
}
// The page will already be cached from the `load` call above.
return (
<PageParamsProvider params={slugsProps}>
<PlasmicComponent component={location.pathname} />
</PageParamsProvider>
);
}
Hey @future_design,
For loader-react I believe your solution to be the best if you want to use the CatchallPage, there won’t be any issues with the slug names.
If you don’t mind listing the specific paths manually, you could try:
function App() {
return (
<PlasmicRootProvider loader={PLASMIC}>
<Router>
<Routes>
<Route path="/echo/:test" element={<PageComponent name={"Homepage"} />} />
<Route path="/plasmic-host" element={<PlasmicCanvasHost />}/>
</Routes>
</Router>
</PlasmicRootProvider>
);
}
function PageComponent(props: { name: string}) {
return <PageParamsProvider params={useParams()} ><PlasmicComponent component={props.name} /></PageParamsProvider>
}