Astro hydration saying not working on renderer

559 views Asked by At

Why I keep getting this error message saying no renderer for react and solidjs ? also why the React component didn't appears on the screen? Below price supposed to be appear a button "add to cart"

enter image description here

The errors are

18:37:01 [renderer] C:/Users/flyingduck/Desktop/astro-frontend-masters/src/components/add-to-cart.tsx No renderer installed for react. Try adding `@astrojs/react` to your project.
18:37:01 [renderer] C:/Users/flyingduck/Desktop/astro-frontend-masters/src/components/cart.tsx No renderer installed for solid-js. Try adding `@astrojs/solid-js` to your project.

This is my astro.config.mjs

import { defineConfig } from 'astro/config';

import solidJs from '@astrojs/solid-js';
import react from '@astrojs/react';

// https://astro.build/config
export default defineConfig({
  integrations: [solidJs(), react()]
});

cart.tsx

import { useStore } from '@nanostores/solid';
import { cart, removeItemFromCart, subtotal } from '../stores/cart';
import styles from './cart.module.css';
import { Show, createSignal } from 'solid-js';

function formatCurrency(amount: number) {
    return new Intl.NumberFormat('en-US', {
        currency: 'usd',
        style: 'currency',
    }).format(amount);
}

const EmptyState = () => {
    return (
        <>
            <p class={styles.icon}>
                <span role="img" aria-label="hot dog">
                    
                </span>
            </p>
            <p class={styles.empty}>
                Your cart is empty! Add a sandwich kit or two and give flavor a chance.
            </p>
        </>
    );
};

const CheckoutNotice = () => {
    return <p class={styles.notice}>Checkout is not implemented yet.</p>;
};

export const Cart = () => {
    const [showNotice, setShowNotice] = createSignal(false);
    const $cart = useStore(cart);
    const $subtotal = useStore(subtotal);

    return (
        <aside class={styles.cart}>
            <h2>Your Cart</h2>
            <Show when={Object.values($cart()).length > 0} fallback={<EmptyState />}>
                <ul class={styles.items}>
                    {Object.values($cart()).map((entry) => {
                        if (!entry) {
                            return null;
                        }

                        return (
                            <li class={styles.item}>
                                <span class={styles.quantity}>{entry.quantity}</span>
                                <span class={styles.name}>{entry.item.title}</span>
                                <span class={styles.remove}>
                                    <button
                                        title="remove item"
                                        onClick={() => removeItemFromCart(entry.item.id)}
                                    >
                                        &times;
                                    </button>
                                </span>
                                <span class={styles.price}>
                                    {formatCurrency(entry.item.price)}
                                </span>
                            </li>
                        );
                    })}
                </ul>

                <div class={styles.details}>
                    <p class={styles.subtotal}>
                        <span class={styles.label}>Subtotal:</span>{' '}
                        {formatCurrency($subtotal())}
                    </p>
                    <p class={styles.shipping}>
                        <span class={styles.label}>Shipping:</span>
                        <del>$10.00</del>
                        <ins>FREE</ins>
                    </p>
                    <p class={styles.total}>
                        <span class={styles.label}>Total:</span>{' '}
                        {formatCurrency($subtotal())}
                    </p>

                    <p class={styles.checkout}>
                        <button class="big-link" onClick={() => setShowNotice(true)}>
                            Check Out
                        </button>
                    </p>

                    <Show when={showNotice()}>
                        <CheckoutNotice />
                    </Show>
                </div>
            </Show>
        </aside>
    );
};

add-to-cart.tsx

/** @jsxImportSource react */

import { addItemToCart } from '../stores/cart';

export const AddToCart = ({ item }: { item: ShopItem }) => {
    return (
        <button className="big-link" onClick={() => addItemToCart(item)}>
            Add To Cart
        </button>
    );
};
2

There are 2 answers

1
ddann On

I fixed with config, migrate to astro v3

First, config

// astro.config.mjs
import { defineConfig } from "astro/config";

import react from "@astrojs/react";
import solid from "@astrojs/solid-js";

export default defineConfig({
  integrations: [
    solid({
      include: ["**/solid/*"],
    }),
    react({
      include: ["**/react/*"],
    }),
  ],
});

Second you need to setup folder structure with Astro v3 guideline, CREATE NEW subfolder like this:

  • /component/react/[...React components here] => [add-to-cart.tsx]
  • /component/solid/[...Solid components here] => [cart.module.css, cart.tsx]

Then, you need fix your import.

1
The Otterlord On

Astro 3.0 introduced changes to the way projects use multiple JSX frameworks.

Astro v3.0 now requires you to specify which framework to use for your files with new include and exclude integration config options when you have multiple JSX framework integrations installed.

Split your components into different directories depending on the JSX framework, then update your config to include these files.

import { defineConfig } from 'astro/config';
import react from '@astrojs/react';
import solid from '@astrojs/solid-js';

export default defineConfig({
  integrations: [
    react({
      include: ['**/react/*']
    }),
    solid({
      include: ['**/solid/*'],
    }),
  ]
});