swr
swr copied to clipboard
useSWRMutation is not working with React Native New Architecture.
Bug report
Repro Steps / Code Example
- npx create-expo-app@latest
configure app.json
"plugins": [
"expo-router",
[
"expo-build-properties",
{
"ios": {
"newArchEnabled": true
},
"android": {
"newArchEnabled": true
}
}
]
],
- home.tsx code example
import useSWRMutation from 'swr/mutation'
function Home () {
const {trigger, data, error} = useSWRMutation('https://github.com', (key) => fetch(key).then(res => res.text()))
console.log({data, error}) // always print {"data": undefined, "error": undefined}
function submit () {
// print error: "(NOBRIDGE) ERROR [TypeError: Cannot read property 'add' of undefined]"
trigger().then(console.log).catch(console.error)
}
return (
<View>
<Button title='mutation' onPress={submit}></Button>
</View>
)
}
I've facing the same issue whenever using the mutation. Probably related to the usage of transition.
This issue requires attention we are unable to work with Expo Go, new architecture is enabled on Expo Go.
Found this ussue ticket - https://github.com/facebook/react-native/issues/47730#issuecomment-2495544910
I encountered this issue as well. Before resolving it on Expo Go, my workaround was to use a development build to continue the development process.
So you are saying it works with the same code used with a dev build? @peterhpchen
@raajnadar . Yes, I didn't change any code from Expo Go to Development Build.
The below is my steps:
- Build:
eas build --profile development --platform ios --local - Run:
npx expo start --dev-client
My eas.json:
{
"build": {
"development": {
"developmentClient": true,
"distribution": "internal",
"android": {
"gradleCommand": ":app:assembleDebug"
},
"ios": {
"buildConfiguration": "Debug"
}
},
},
}
Did you try running it with a preview build, an apk or a test flight build? Because that did not work for me, let me check with the dev client build.
@raajnadar, sorry for the confusion. After some configuration changes, I realized I had disabled the New Architecture in the development build. When I enable the New Architecture ("newArchEnabled": true), I encounter the same Cannot read property 'add' of undefined error.
ref: https://docs.expo.dev/guides/new-architecture/#disable-the-new-architecture-in-an-existing-project
So we can surely say the issue is with the new architecture and also it is in core react native, there is no problem in SWR library.
Please share any feedback you have in the React native thread, I created a thread to follow up and escalate the issue.
https://github.com/facebook/react-native/issues/47947
Seems like it works in new arch without data and isMutating
This works: const { trigger } = useSWRMutation(... but this doesnt const { trigger, data } = useSWRMutation...
So my solution was using useSWRMutation like this:
const [data, setData] = useState(null);
const { trigger } = useSWRMutation('/api/user', updateUser);
useEffect(()=>{
trigger().then(res=>setData(res))
}, [])
The whole point of SWR was to avoid the usage of useEffect by devs for data fetching and to prevent edge cases & memory leaks in the application.
The whole point of SWR was to avoid the usage of useEffect by devs for data fetching and to prevent edge cases & memory leaks in the application.
yes, this is a quick solution for the devs who use the new arch and dont want to migrate all triggers
You can use this patch this works for me
diff --git a/node_modules/swr/dist/mutation/index.js b/node_modules/swr/dist/mutation/index.js
index 0e34690..8607e14 100644
--- a/node_modules/swr/dist/mutation/index.js
+++ b/node_modules/swr/dist/mutation/index.js
@@ -542,9 +542,9 @@ _internal.OBJECT.defineProperty(_internal.SWRConfig, 'defaultValue', {
* ```
*/ const useSWR = _internal.withArgs(useSWRHandler);
-const startTransition = _internal.IS_REACT_LEGACY ? (cb)=>{
- cb();
-} : ReactExports__default.default.startTransition;
+// const startTransition = _internal.IS_REACT_LEGACY ? (cb)=>{
+// cb();
+// } : ReactExports__default.default.startTransition;
/**
* An implementation of state with dependency-tracking.
*/ const useStateWithDeps = (state)=>{
@@ -610,6 +610,7 @@ const startTransition = _internal.IS_REACT_LEGACY ? (cb)=>{
};
const mutation = ()=>(key, fetcher, config = {})=>{
+ const [, startTransition] = ReactExports.useTransition()
const { mutate } = _internal.useSWRConfig();
const keyRef = ReactExports.useRef(key);
const fetcherRef = ReactExports.useRef(fetcher);
any news? same issue here
Why this bug still not fixed?
I don't understand the cause of the issue and this implementation doesn't have any problem on other environments, why doesn't this work on the new architecture?
The patch also worked for me, just added in node_modules/swr/dist/mutation/index.js
//find this line const mutation = ()=>(key, fetcher, config = {})=>{ //and added below const [, startTransition] = React.useTransition();
I have the same error and this fix the error: https://github.com/vercel/swr/issues/2986#issuecomment-2561904700
Thank you and I hope the swr team can do something about it.
The patch also worked for me, just added in node_modules/swr/dist/mutation/index.js
//find this line const mutation = ()=>(key, fetcher, config = {})=>{ //and added below const [, startTransition] = React.useTransition();
patch doesn't work well. I'll switch to react-query
+1 isMutating is always true and the data is always undefined after calling trigger(), I use expo 52 with newArchEnabled
Same here.
I think, developers won't fix this. I fixed swr like in comment above and vendor it in my project locally
This issue is brutal! Please fix @team
Seems like it works in new arch without
dataandisMutatingThis works:
const { trigger } = useSWRMutation(...but this doesntconst { trigger, data } = useSWRMutation...So my solution was using
useSWRMutationlike this:const [data, setData] = useState(null); const { trigger } = useSWRMutation('/api/user', updateUser);
useEffect(()=>{ trigger().then(res=>setData(res)) }, [])
i tested this "solution", is not working.