React Integration
The @ecopages/react package introduces first-class integration with React version 19, enabling developers to build dynamic components using the latest React features within the Ecopages platform.
Installation
bunx jsr add @ecopages/reactUsage
To enable React support, add the reactPlugin to your Ecopages configuration.
import { ConfigBuilder } from '@ecopages/core';
import { reactPlugin } from '@ecopages/react';
const config = await new ConfigBuilder()
.setRootDir(import.meta.dir)
.setBaseUrl(import.meta.env.ECOPAGES_BASE_URL)
.setIntegrations([reactPlugin()])
.build();
export default config;Creating Components
Standard (eco.component)
The standard way to create components in Ecopages is via the eco.component factory. This is ideal for managing dependencies (scripts, stylesheets) and enabling advanced features like lazy loading.
import { useState } from 'react';
import { eco } from '@ecopages/core';
export const Counter = eco.component({
dependencies: {
stylesheets: ['./counter.css'],
},
render: () => {
const [count, setCount] = useState(0);
return (
<div className="counter">
<p>Count: {count}</p>
<button onClick={() => setCount(prev => prev - 1)}>-</button>
<button onClick={() => setCount(prev => prev + 1)}>+</button>
</div>
);
}
});Plain React Components
Thanks to Bun's automatic bundling, you can also write standard React components just like in any other React framework.
This is especially useful if you are using Tailwind CSS, as you do not need to attach specific stylesheets or declare dependencies.
import { useState } from 'react';
export function SimpleCounter() {
const [count, setCount] = useState(0);
return (
<button
className="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600"
onClick={() => setCount(count + 1)}
>
Count: {count}
</button>
);
}Using in Pages
Import your component and include it in your page. Don't forget to register it in the page's dependencies.
import { Counter } from '@/components/counter';
import { BaseLayout } from '@/layouts/base-layout';
import { eco } from '@ecopages/core';
export default eco.page({
dependencies: {
components: [BaseLayout, Counter],
},
render: () => {
return (
<BaseLayout>
<h1>Welcome to React on Ecopages</h1>
<Counter />
</BaseLayout>
);
}
});Utilities
dynamic
Use the dynamic utility to lazy-load components or render them only on the client.
import { dynamic } from '@ecopages/react/utils/dynamic';
const HeavyComponent = dynamic(() => import('@/components/heavy-chart'), {
ssr: false, // Defaults to true
loading: () => <p>Loading chart...</p>
});ClientOnly
The ClientOnly component is useful for parts of the UI that should strictly render in the browser (e.g., accessing window or localStorage).
import { ClientOnly } from '@ecopages/react/utils/client-only';
<ClientOnly fallback={<Spinner />}>
<BrowserSpecificFeature />
</ClientOnly>Key Features
- React 19: Full support for Server Components concepts and latest hooks.
- Fast Refresh: Built-in Hot Module Replacement (HMR) for instant feedback.
- TypeScript: First-class type definitions.
- Streaming: (Coming Soon) Support for React Server Components streaming.
MDX Support
The React plugin includes optional MDX support. When enabled, you can author .mdx pages alongside .tsx pages with unified client-side routing, hydration, and HMR.
import { ConfigBuilder } from '@ecopages/core';
import { reactPlugin } from '@ecopages/react';
import { ecoRouter } from '@ecopages/react-router';
const config = await new ConfigBuilder()
.setRootDir(import.meta.dir)
.setBaseUrl(import.meta.env.ECOPAGES_BASE_URL)
.setIntegrations([
reactPlugin({
router: ecoRouter(),
mdx: {
enabled: true,
compilerOptions: {
// Optional: remark/rehype plugins
},
},
}),
])
.build();
export default config;This is the recommended approach when using a client-side router, as it ensures seamless navigation between TSX and MDX pages.