Skip to main content
This guide helps you migrate between major versions of React Turnstile.

Current Version

The latest stable version is v1.4.2. This library follows semantic versioning.

Migrating to v1.4.x

What’s New

  • v1.4.2: Security dependency updates and bug fixes
  • v1.4.1: Fixed race condition when loading Turnstile script
  • v1.4.0: Updated dependencies and CI configurations

Changes

Fixed: Security vulnerabilities in dependenciesNo breaking changes. Update normally:
npm install @marsidev/[email protected]
What’s Fixed:
  • feedbackEnabled option can now be set to false properly
  • Security patches for minimatch, rollup, and ajv
Fixed: Widget sometimes fails to render due to script loading race conditionNo code changes required. The fix is automatic:
npm install @marsidev/[email protected]
What’s Fixed:
  • Script loading race condition resolved
  • Widget now polls for window.turnstile to ensure proper initialization

Migrating to v1.3.x

What’s New

  • v1.3.0: Added rerenderOnCallbackChange prop
  • v1.3.1: Fixed getResponsePromise return type

Changes

Added: New rerenderOnCallbackChange prop to control widget re-renderingMigration: No changes required. This is a new opt-in feature.Before (stale closures issue):
const [count, setCount] = useState(0)

// This callback captures the initial count value
const handleSuccess = (token: string) => {
  console.log('Count:', count) // Always logs 0
}

return <Turnstile siteKey="..." onSuccess={handleSuccess} />
After (fixed with new prop):
const [count, setCount] = useState(0)

const handleSuccess = useCallback((token: string) => {
  console.log('Count:', count) // Logs current count
}, [count])

return (
  <Turnstile 
    siteKey="..."
    onSuccess={handleSuccess}
    rerenderOnCallbackChange={true}
  />
)
Note: The default behavior is unchanged (rerenderOnCallbackChange={false}).
Fixed: getResponsePromise return type now correctly excludes undefinedMigration: If you were using type assertions, you can remove them:Before:
const token = await turnstileRef.current?.getResponsePromise()
if (token) {
  // token might be undefined
}
After:
// token is guaranteed to be string (or throws)
const token = await turnstileRef.current!.getResponsePromise()

Migrating to v1.2.x

Changes

Fixed: Missing dependencies in renderConfig causing stale propsMigration: No code changes required. Update normally:
npm install @marsidev/[email protected]
The widget now properly re-renders when options change.

Migrating to v1.1.x

Changes

Added: Support for React 19Migration: No changes required. The library now supports React 17, 18, and 19:
{
  "peerDependencies": {
    "react": "^17.0.2 || ^18.0.0 || ^19.0",
    "react-dom": "^17.0.2 || ^18.0.0 || ^19.0"
  }
}

Migrating to v1.0.x

Breaking Changes

Breaking: Library now ships as ESM onlyMigration:
  1. Ensure your project supports ESM For Next.js, ensure you’re on Next.js 13+:
    {
      "type": "module"
    }
    
  2. Update peer dependencies React 17+ is now required:
    npm install react@^18.0.0 react-dom@^18.0.0
    
  3. Update imports No changes to import syntax, but ensure your bundler supports ESM.
What Changed:
  • CommonJS builds removed
  • Only ESM exports available
  • Minimum React version is now 17.0.2
Breaking: autoResetOnExpire prop removedMigration: Use refreshExpired option insteadBefore:
<Turnstile
  siteKey="your-site-key"
  autoResetOnExpire={false}
/>
After:
<Turnstile
  siteKey="your-site-key"
  options={{
    refreshExpired: 'manual' // or 'never' or 'auto'
  }}
/>
Values:
  • 'auto' (default): Automatically refresh when expired
  • 'manual': Show refresh button to user
  • 'never': Never refresh
Fixed: Missing 'use client' directive in build outputMigration: No changes required if you’re already using client components.This fix ensures the library works properly in Next.js App Router without manual configuration.
Fixed: Added default exports for better compatibilityMigration: Both import styles now work:
// Named import (recommended)
import { Turnstile } from '@marsidev/react-turnstile'

// Default import (now supported)
import Turnstile from '@marsidev/react-turnstile'

Version History

VersionRelease DateKey Changes
1.4.22025-03Security updates, feedbackEnabled fix
1.4.12025-02Race condition fix
1.4.02025-01Dependency updates
1.3.12024TypeScript improvements
1.3.02024rerenderOnCallbackChange prop
1.2.02024renderConfig dependencies fix
1.1.02024React 19 support
1.0.22024Default exports
1.0.12024’use client’ directive fix
1.0.02024ESM only, refreshExpired option

Upgrade Path

From 0.x to Latest

If you’re on a very old version, upgrade incrementally:
# 1. Upgrade to 1.0.x first
npm install @marsidev/[email protected]

# 2. Fix breaking changes (see v1.0.0 section above)

# 3. Upgrade to latest
npm install @marsidev/react-turnstile@latest

From 1.x to Latest

No breaking changes within 1.x versions:
npm install @marsidev/react-turnstile@latest

Getting Help

If you encounter issues during migration:
  1. Check the Troubleshooting Guide
  2. Review GitHub Issues
  3. Read the Changelog
  4. Open a new issue with your migration problem

Stay Updated

GitHub Releases

Subscribe to release notifications

npm Package

View package updates

Build docs developers (and LLMs) love