Bug: startTransition is causing TypeError when used directly from react
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
- Run the code example https://snack.expo.dev/@raajnadar/swr-error-in-expo-sdk-52
- Run android or ios, the web version works without the error
- Click the "Call the API button" button inside the mobile app
- Check the logs tab, when switched to axios there is no issue
- This happens with
swrbecause 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
Maybe related issue? https://github.com/facebook/react-native/issues/47730
[!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.
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
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.
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
It's from Vercel so I assumed it to be popular maybe RN devs don't prefer using SWR
But this issue seems related and posted by another dev with more information https://github.com/facebook/react-native/issues/47730
same
But the "State of React Native" survey has the mention of SWR in the data fetching section
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 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
@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.
facing that today any solution?
@mateoguzmana but how can the bug be in
useSWRMutationhook 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.
Same here.
same here
The issue disappeared on SDK 53.