Skip to content

Using with Remix: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object. #24

Closed

Description

@biot023

Hello -- I'm trying to use the Turnstile component in a Remix app, like so:

import React from 'react';
import { Form } from "@remix-run/react";
import Turnstile, { useTurnstile } from "react-turnstile";

export default function Contact() {
  const turnstile = useTurnstile();

  return (
    <div>
      <h1>Contact me</h1>
      <Form method="post">
        <legend>Please enter message details</legend>
        <p>
          <input type="email" name="email" class="bg-transparent border-2 border-solid border-slate-50 rounded-sm"/>
        </p>
        <p>
          <textarea name="message" class="bg-transparent border-2 border-solid border-slate-50 rounded-sm"></textarea>
        </p>
        <Turnstile
          sitekey="1x00000000000000000000AA"
        />
        <button type="submit">Send message</button>
      </Form>
    </div>
  );
}

However, when I try to browse to this route, I get this error:

[ERROR] Warning: React.jsx: type is invalid -- expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check your code at contact.tsx:19.

Line 19, that it mentions in the error, is where the Turnstile component is declared.

Is this something anyone else has come across? And can they offer any advice, if they have?
Thank you,
Doug.

Activity

  1. Yaroslavpnts commented on Jul 25, 2024

    @Yaroslavpnts

    Have the same problem.
    @biot023
    Did you managed it?

  2. emqMalte commented on Aug 3, 2024

    @emqMalte

    I worked around this by letting the Turnstile component only render on the client via ClientOnly from https://sergiodxa.github.io/remix-utils/#md:clientonly

  3. dmm9 commented on Aug 11, 2024

    @dmm9

    You need to render only on the client. With ClientOnly as emqMalte said, or with useEffect:

    export default function ComponentWithTurnstile() {
      const [isClient, setIsClient] = useState(false);
      useEffect(() => {
        setIsClient(true);
      }, []);
    
      return (
        ...
        {isClient && <Turnstile ... />}
      )
    }
  4. Le0Developer commented on Jan 30, 2026

    @Le0Developer
    Owner

    I believe the original issue should be fixed by #45 which just landed in v1.1.15; use import { Turnstile, useTurnstile } from "react-turnstile" if you run into this.

    This library is still client-side only, so "use client" directives or other hacks that prevent SSR are necessary.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions