zod icon indicating copy to clipboard operation
zod copied to clipboard

v4: Error - "Cannot call a class as a function" in React Native.

Open mcculloughrt-svh opened this issue 8 months ago β€’ 7 comments

Building a schema with zod v4 (for example simply const str = z.string(), any schema construction method will cause the error) in an Expo project throws a "Cannot call a class as a function" error.

I was able to confirm a minimal repro by using npx create-expo-app@latest, adding zod v4, and adding the above string parse line to the home component function body, and nothing else.

There's no indication of deeper error source. No linter error occurs, and it's such a basic functionality that I know works in other environments I suspect something fishy is happening with the Metro bundling process and the $constructor function from @zod/core.

mcculloughrt-svh avatar Apr 14 '25 16:04 mcculloughrt-svh

This seems like a dual package hazard issue, and since RN 0.79 the unstable_enablePackageExports option is enable by default https://github.com/facebook/metro/pull/1448.

I created a repro with Expo SDK 53, which came with RN 0.79. As soon as you import zod, it starts throwing the error. If you try to opt-out of unstable_enablePackageExports, it will not be able to resolve some of the modules. https://github.com/chungweileong94/RN-zod-v4-bug

chungweileong94 avatar Apr 17 '25 13:04 chungweileong94

Is there any progress or other workarounds for this? We're also seeing this issue and I'm surprised no one else is hitting it with React Native.

rikbrown avatar May 06 '25 12:05 rikbrown

Is there any progress or other workarounds for this? We're also seeing this issue and I'm surprised no one else is hitting it with React Native.

So far based on what I'm noticing is that you will hit the (similar) issue if you are using:

  • Zod v3 + RN with unstable_enablePackageExports
  • Zod v4 + RN

Both of these combinations are considered pretty new, unstable_enablePackageExports only got enabled by default in the recent RN/Expo release, and usually RN dev don't upgrade that often, so it makes sense that not many people are hitting this issue just yet. As for Zod v4, it's beta🀷

For now, my workaround is to stay on Zod v3, and make sure the unstable_enablePackageExports is off.

chungweileong94 avatar May 07 '25 02:05 chungweileong94

I'm also experiencing this. I tried several combinations of package exports but none of them seemed to resolve my issue. I tried:

  • Adding a react-native export key for all fields to the commonjs build
  • Removing all the export keys to force it to go to commonjs
  • config.resolver.unstable_enablePackageExports = false reveals there is an issue with parsing @zod/core.
  • I also tried an option where I resolved only the source development build, but the .js extensions in the the source files in @zod/core could not be resolved by Metro.

joshuayoes avatar May 07 '25 23:05 joshuayoes

facing the same issue. It only happens at ios and android though. web build won't have this issue

jcppman avatar May 13 '25 10:05 jcppman

This is not fixed yet with the new zod/v4 package.

tobimori avatar May 16 '25 13:05 tobimori

Has anyone managed to get round it?

abanobboles avatar May 20 '25 20:05 abanobboles

@colinhacks any chance to look on this; please

abanobboles avatar May 21 '25 14:05 abanobboles

I'm having this same issue in a regular react/webpack/typescript project, with no metro/RN/hermes stuff... can anyone point me in the right direction for where to start debugging my config?

or should I be waiting for the RN fix and hoping it helps?

edit: looked a bit closer and noticed it reproduces in the most simple react/ts template i could find, so i guess there's probably nothing specific to RN here (though i'm guessing that also means that work towards fixing RN will also fix other uses)

mrobb-twitch avatar May 22 '25 23:05 mrobb-twitch

using [email protected] solved the issue for me.

rdnsan avatar May 23 '25 07:05 rdnsan

Landed in stable: [email protected]

colinhacks avatar May 23 '25 18:05 colinhacks

I encountered the "Cannot call a class as a function" error in my React Native project, and after investigation, I found the root cause was an import conflict between React Native's Text component and SVG's Text component.

The Problem In my StepCounter.tsx file, I was using the Text component without properly importing it from react-native:

// ❌ WRONG - Missing Text import
import { View } from "react-native";

// Later in the component:
<Text style={{...}}>Some text</Text> // This caused the error!

Meanwhile, my ProgressRingDisplay.tsx file had both imports:

// βœ… CORRECT - Both imports present
import { View, Text } from "react-native";
import Svg, { Text as SvgText, G, Path, ... } from "react-native-svg";

Why This Happens When you don't explicitly import Text from react-native but you have SVG components in your component tree (either directly or through child components), React Native's bundler can get confused about which Text component to use. The SVG Text component is a class-based component meant for SVG rendering, while React Native's Text is a function component for regular text display.

Trying to use the SVG Text component as a regular text component results in the "Cannot call a class as a function" error because the bundler attempts to call the SVG Text class as if it were a function component.

The Solution Simply add Text to your React Native imports:

// βœ… FIXED
import { View, Text } from "react-native";

Key Takeaways

  • Always explicitly import components you use, even if they seem to work without imports initially
  • Watch out for naming conflicts between different libraries (react-native vs react-native-svg)
  • This error can be misleading - it's not always about calling classes as functions, but often about import resolution conflicts
  • Check your imports first when encountering this error, especially in projects mixing different UI libraries

When This Might Happen to You

  • Mixing react-native and react-native-svg components
  • Using components without proper imports in complex component hierarchies
  • Working with any libraries that have overlapping component names
  • Metro bundler resolving imports differently than expected

This issue is different from the Zod v4 React Native compatibility issues that others have reported - it's specifically about import conflicts within your own codebase.

Senzo13 avatar Jul 19 '25 03:07 Senzo13

I encountered the "Cannot call a class as a function" error in my React Native project, and after investigation, I found the root cause was an import conflict between React Native's Text component and SVG's Text component.

The Problem In my StepCounter.tsx file, I was using the Text component without properly importing it from react-native:

// ❌ WRONG - Missing Text import
import { View } from "react-native";

// Later in the component:
<Text style={{...}}>Some text</Text> // This caused the error!

Meanwhile, my ProgressRingDisplay.tsx file had both imports:

// βœ… CORRECT - Both imports present
import { View, Text } from "react-native";
import Svg, { Text as SvgText, G, Path, ... } from "react-native-svg";

Why This Happens When you don't explicitly import Text from react-native but you have SVG components in your component tree (either directly or through child components), React Native's bundler can get confused about which Text component to use. The SVG Text component is a class-based component meant for SVG rendering, while React Native's Text is a function component for regular text display.

Trying to use the SVG Text component as a regular text component results in the "Cannot call a class as a function" error because the bundler attempts to call the SVG Text class as if it were a function component.

The Solution Simply add Text to your React Native imports:

// βœ… FIXED
import { View, Text } from "react-native";

Key Takeaways

  • Always explicitly import components you use, even if they seem to work without imports initially
  • Watch out for naming conflicts between different libraries (react-native vs react-native-svg)
  • This error can be misleading - it's not always about calling classes as functions, but often about import resolution conflicts
  • Check your imports first when encountering this error, especially in projects mixing different UI libraries

When This Might Happen to You

  • Mixing react-native and react-native-svg components
  • Using components without proper imports in complex component hierarchies
  • Working with any libraries that have overlapping component names
  • Metro bundler resolving imports differently than expected

This issue is different from the Zod v4 React Native compatibility issues that others have reported - it's specifically about import conflicts within your own codebase.

This help .Thanks

opezyhick avatar Aug 30 '25 14:08 opezyhick