React
React SPA client-side rendering with React DOM Router
Render all blog routes under /posts/*
using client-side data fetching.
1) main.tsx
import { createRoot } from 'react-dom/client';
import { BrowserRouter, Routes, Route } from 'react-router-dom';
import { Provider } from './providers';
import BlogEntryPage from './BlogEntryPage';
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
<BrowserRouter>
<Provider>
<Routes>
<Route path="/posts/*" element={<BlogEntryPage />} />
</Routes>
</Provider>
</BrowserRouter>
)
2) BlogEntryPage.tsx
import { useLocation } from "react-router-dom"
import { BlogRouterPage } from "better-blog/client"
export default function BlogEntryPage() {
const location = useLocation()
return (
<main >
<BlogRouterPage path={location.pathname} />
</main>
)
}
3) providers.tsx
import { QueryClientProvider } from "@tanstack/react-query";
import type { ReactNode } from "react";
import { NavLink, useNavigate } from "react-router-dom"
import { BetterBlogContextProvider } from "better-blog/client";
import type { ComponentsContextValue, BlogDataProvider, getDefaultQueryClient } from "better-blog";
import { ThemeProvider } from "./theme-provider";
// React router DOM link and simple image
const components: ComponentsContextValue = {
Link: ({ href, children, className }) => (
<NavLink to={href.replace('/posts', '/blog')} className={className}>
{children}
</NavLink>
),
Image: ({ src, alt, className }) => (
<img src={src} alt={alt} className={className} />
),
};
// Implement your data provider here
const clientBlogConfig: BlogDataProvider = {
...
};
export function Provider({ children }: { children: ReactNode }) {
const queryClient = getQueryClient();
const navigate = useNavigate()
return (
<QueryClientProvider client={queryClient}>
<ThemeProvider>
<BetterBlogContextProvider
localization={{
BLOG_LIST_TITLE: "Blog Posts",
}}
clientConfig={clientBlogConfig}
components={components}
navigate={navigate}
basePath="/blog"
adminUiOptions={{
canCreate:true,
canUpdate:true,
canDelete:true
}}
uploadImage={async (file) => {
console.log("uploadImage", file);
// implement your own image upload logic here
return "https://via.placeholder.com/150/png";
}}
>
{children}
</BetterBlogContextProvider>
</ThemeProvider>
</QueryClientProvider>
);
}