v 0.1.104

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/react

Usage

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

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.