react-native icon indicating copy to clipboard operation
react-native copied to clipboard

Bug: startTransition is causing TypeError when used directly from react

Open raajnadar opened this issue 1 year ago • 16 comments

Description

Getting this error message when using SWR with expo SDK 52, this issue was not present in expo SDK 51. This issue is only present on android and ios for react native web the SWR calls works without any type error.

TypeError: Cannot read property 'add' of undefined

On Expo snack the error says

Error: "Cannot read property 'add' of undefined" in TypeError: Cannot read property 'add' of undefined << at requestUpdateLane (/data/user/0/host.exp.exponent/files/.expo-internal/5cb1b0c52b8fcab94364327c83b808ee:18892:43) << at dispatchSetState (/data/user/0/host.exp.exponent/files/.expo-internal/5cb1b0c52b8fcab94364327c83b808ee:16726:33) << at anonymous (swr.mutation:12:14616)

This is how SWR is using the startTransition API, When I tried using the startTransition from the useTransition hook the problem got solved

export const startTransition: (scope: TransitionFunction) => void =
  IS_REACT_LEGACY
    ? cb => {
        cb()
      }
    : React.startTransition

And use like this

startTransition(() =>
   setState({ data, isMutating: false, error: undefined })
)

Code from this repository https://github.com/vercel/swr/blob/1585a3e37d90ad0df8097b099db38f1afb43c95d/src/mutation/state.ts#L5-L10

Some of my findings are here - https://github.com/facebook/react/issues/31622

Steps to reproduce

  1. Run the code example https://snack.expo.dev/@raajnadar/swr-error-in-expo-sdk-52
  2. Run android or ios, the web version works without the error
  3. Click the "Call the API button" button inside the mobile app
  4. Check the logs tab, when switched to axios there is no issue
  5. This happens with swr because it uses startTransition internally

React Native Version

0.76.3

Affected Platforms

Runtime - Android, Runtime - iOS

Output of npx react-native info

System:
  OS: macOS 14.2.1
  CPU: (10) arm64 Apple M1 Pro
  Memory: 102.55 MB / 16.00 GB
  Shell:
    version: "5.9"
    path: /bin/zsh
Binaries:
  Node:
    version: 18.19.0
    path: ~/.nvm/versions/node/v18.19.0/bin/node
  Yarn:
    version: 1.22.19
    path: /usr/local/bin/yarn
  npm:
    version: 10.2.3
    path: ~/.nvm/versions/node/v18.19.0/bin/npm
  Watchman: Not Found
Managers:
  CocoaPods:
    version: 1.12.0
    path: /Users/chris/.rbenv/shims/pod
SDKs:
  iOS SDK:
    Platforms:
      - DriverKit 23.4
      - iOS 17.4
      - macOS 14.4
      - tvOS 17.4
      - visionOS 1.1
      - watchOS 10.4
  Android SDK: Not Found
IDEs:
  Android Studio: 2024.2 AI-242.21829.142.2421.12409432
  Xcode:
    version: 15.3/15E204a
    path: /usr/bin/xcodebuild
Languages:
  Java:
    version: 17.0.12
    path: /usr/bin/javac
  Ruby:
    version: 2.7.5
    path: /Users/chris/.rbenv/shims/ruby
npmPackages:
  "@react-native-community/cli":
    installed: 15.0.1
    wanted: 15.0.1
  react:
    installed: 18.3.1
    wanted: 18.3.1
  react-native:
    installed: 0.76.2
    wanted: 0.76.2
  react-native-macos: Not Found
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: true
iOS:
  hermesEnabled: true
  newArchEnabled: true

Stacktrace or Logs

TypeError: Cannot read property 'add' of undefined
    at requestCurrentTransition (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:13106:36)
    at requestUpdateLane (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:15752:50)
    at dispatchSetState (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:9607:37)
    at anonymous (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:373831:17)
    at anonymous (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:373890:32)
    at startTransition (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:20591:16)
    at ?anon_0_ (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:373889:30)
    at next (native)
    at asyncGeneratorStep (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:23563:19)
    at _next (http://localhost:8081/index.bundle//&platform=ios&dev=true&lazy=true&minify=false&inlineSourceMap=false&modulesOnly=false&runModule=true&excludeSource=true&sourcePaths=url-server&app={BUNDLE_ID}:23577:29)
    at tryCallOne (address at InternalBytecode.js:1:1180)
    at anonymous (address at InternalBytecode.js:1:1874)

Reproducer

https://snack.expo.dev/@raajnadar/swr-error-in-expo-sdk-52

Screenshots and Videos

No response

raajnadar avatar Nov 26 '24 09:11 raajnadar

Maybe related issue? https://github.com/facebook/react-native/issues/47730

raajnadar avatar Nov 26 '24 09:11 raajnadar

[!NOTE] Expo related: It looks like your issue is related to Expo and not React Native core. Please open your issue in Expo's repository. If you are able to create a repro that showcases that this issue is also happening in React Native vanilla, we will be happy to re-open.

react-native-bot avatar Dec 03 '24 13:12 react-native-bot

Actually reopening as the issue might be related to react-native core. I currently don't have capacity to investigate this one, but it would be great if you could opne an issue on gh/expo/expo as well

cortinico avatar Dec 03 '24 13:12 cortinico

It seems the expo team is not interested in looking into the issue, they closed the issue saying this issue is from react native core.

It is surprising to see why other devs are not getting this issue, I though SWR is a popular library or maybe devs are not using SWR with react native.

raajnadar avatar Dec 06 '24 16:12 raajnadar

It is surprising to see why other devs are not getting this issue, I though SWR is a popular library or maybe devs are not using SWR with react native.

To be fair, I had to google was SWR is. That's the first time I see it mentioned in the issue tracker for React Native in 3+ years

cortinico avatar Dec 06 '24 17:12 cortinico

It's from Vercel so I assumed it to be popular maybe RN devs don't prefer using SWR

raajnadar avatar Dec 06 '24 17:12 raajnadar

But this issue seems related and posted by another dev with more information https://github.com/facebook/react-native/issues/47730

raajnadar avatar Dec 06 '24 18:12 raajnadar

same

AntoninSorrento avatar Dec 11 '24 04:12 AntoninSorrento

But the "State of React Native" survey has the mention of SWR in the data fetching section

Screenshot 2024-12-15 at 4 30 52 PM

raajnadar avatar Dec 15 '24 11:12 raajnadar

I’m trying to narrow down the issue by creating a reproduction example without external dependencies. Otherwise, it’s difficult to pinpoint the problem if it’s indeed an issue in the core.

Code snippet trying to mimic the reproducer without third party deps
import React, {useState} from 'react';
import {ActivityIndicator, Button, StyleSheet, Text, View} from 'react-native';

export const IS_REACT_LEGACY = !React.useId;

export const startTransition: (scope: () => void) => void = IS_REACT_LEGACY
  ? cb => {
      cb();
    }
  : React.startTransition;

const API_URL = 'https://jsonplaceholder.typicode.com/posts';

function Playground() {
  const [apiResponse, setApiResponse] = useState(null);
  const [isFetching, setIsFetching] = useState(false);

  const callApi = () => {
    setIsFetching(true);

    startTransition(async () => {
      try {
        const response = await fetch(API_URL, {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({
            title: 'foo',
            body: 'bar',
            userId: 3,
          }),
        });

        if (!response.ok) {
          throw new Error(`HTTP error! status: ${response.status}`);
        }

        const data = await response.json();
        console.log(data);
        setApiResponse(data);
      } catch (error) {
        console.error(error);
        setApiResponse({error: 'Failed to fetch data'});
      } finally {
        setIsFetching(false);
      }
    });
  };

  return (
    <View style={styles.container}>
      <Text style={styles.title}>API Call with startTransition</Text>
      <Button title="Call the API" onPress={callApi} />
      {isFetching && <ActivityIndicator style={styles.spinner} />}
      {apiResponse && (
        <Text style={styles.response}>
          {apiResponse.error
            ? apiResponse.error
            : JSON.stringify(apiResponse, null, 2)}
        </Text>
      )}
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    marginTop: 70,
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 16,
    backgroundColor: '#fff',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 16,
  },
  spinner: {
    marginVertical: 16,
  },
  response: {
    marginTop: 16,
    fontSize: 14,
    color: '#333',
    textAlign: 'center',
  },
});

I’m not seeing the issue with my code above. If possible, could you try reproducing the problem without those dependencies? That way, we can determine if there’s something in the useSWRMutation hook that might be influencing the issue.

mateoguzmana avatar Jan 16 '25 03:01 mateoguzmana

@mateoguzmana did you try this with Expo Go? For all my testing I used Expo Go or dev client.

Edit - This solution was a quick fix

https://github.com/vercel/swr/issues/2986#issuecomment-2561904700

raajnadar avatar Jan 16 '25 13:01 raajnadar

@mateoguzmana but how can the bug be in useSWRMutation hook if that works in Expo SDK 51 and stopped working in Expo SDK 52 there was no release in SWR the only thing that changed was the expo version and the dependent React Js & React Native version.

I will try to run with vanilla React Native that Expo SDK 52 runs.

raajnadar avatar Jan 18 '25 10:01 raajnadar

facing that today any solution?

krolow avatar Feb 25 '25 18:02 krolow

@mateoguzmana but how can the bug be in useSWRMutation hook if that works in Expo SDK 51 and stopped working in Expo SDK 52 there was no release in SWR the only thing that changed was the expo version and the dependent React Js & React Native version.

I will try to run with vanilla React Native that Expo SDK 52 runs.

For my project, this manifested with the new architecture specifically. I was able to upgrade to Expo 52 successfully, but have set newArchEnabled: false to avoid the TypeError for now.

coren-frankel avatar Mar 31 '25 16:03 coren-frankel

Same here.

caioedut avatar Apr 24 '25 16:04 caioedut

same here

w4t3r-45 avatar May 27 '25 10:05 w4t3r-45

The issue disappeared on SDK 53.

raajnadar avatar Aug 12 '25 12:08 raajnadar