react-native-reanimated
react-native-reanimated copied to clipboard
Shared Element transition does not work after adding @react-native-firebase on iOS
Description
took the problem from here https://github.com/software-mansion/react-native-reanimated/discussions/4691 but also just have the same.
Steps to reproduce
- To repro just setup basic project with transition (like in reanimated Examples)
- After that setup firebase via their instructions.
Snack or a link to a repository
https://github.com/software-mansion/react-native-reanimated/blob/4cba573aad640db1e8912455f1877fbab815f0d3/app/src/examples/SharedElementTransitions/ProgressTransition.tsx
Reanimated version
3.4.1
React Native version
0.72.3
Platforms
iOS
JavaScript runtime
Hermes
Workflow
React Native (without Expo)
Architecture
Paper (Old Architecture)
Build type
Debug mode
Device
iOS simulator
Device model
any
Acknowledgements
Yes
Hey! 👋
The issue doesn't seem to contain a minimal reproduction.
Could you provide a snack or a link to a GitHub repository under your username that reproduces the problem?
Hey 👋 Which version of rn-screens do you have?
Interesting observation! I just tried to get shared element transitions working with the latest reanimated and latest react-navigation, but it doesn't work. I've also got Firebase integrated but don't know if it's related. However, I always get a warning like [Reanimated] Duplicate shared tag "tag" on the same screen
even with the basic examples for documentation.
I believe it's use_frameworks that breaks it not necessarily just firebase. Related: https://github.com/software-mansion/react-native-reanimated/issues/4337
Indeed, I tried the same code base from the React Navigation documentation in both the Firebase/Flipper-setup project and the non-Firebase project. It works well in the non-Firebase setup project, but not in the Firebase project, with a warning log of [Reanimated] Duplicate shared tag "tagName" on the same screen.
When will there be an update for this problem? dear @tjzel
@rockstar0711 I've been sick lately and got a lot of work that piled up. I'll try to get into it eventually.
Oh, Sorry to hear about that. I hope that you get better soon. Thank you for your hard work! Cheers! 👍💪
Upvoting this, having the same issue
I finally had some time to dig into it, and here are the results.
What
The problem is not with Firebase itself, but the Podfile
option it requires for the installation, as you have mentioned:
use_frameworks! :linkage => :static
Adding this line changes how linking is made and because of that the macro defined here resolves to false
.
This macro is a simple check if the user has react-native-screens
installed (the header is accessible). If yes, then we use actual Shared Element Transitions implementation. If not, then we load a mock. So in this case, we incorrectly use the mock. "Duplicate shared tag" error happening here is just a coincidence - it doesn't have a mock (but it should have).
From what I understand, this is happening because react-native-screens
is not a dependency of Reanimated, and using dynamic workflows means it's unavailable (unaccessible) at compile-time, even though static linking is on.
Solution
For the time being, I've found a workaround for it. All you need to do is to add the following to your Podfile
:
pre_install do |installer|
installer.pod_targets.each do |pod|
if pod.name.eql?('RNScreens')
def pod.build_type
Pod::BuildType.static_library
end
end
end
end
This will make RNScreens
a static library instead of a dynamic workflow and from my testing everything was working fine.
Notes
Unfortunately, we haven't yet found an elegant solution that wouldn't require additional input from the user (adding to Podfile
). By elegant, I mean a way to find if react-native-screens
is installed without digging through node_modules
with some scripts or else. If someone has some experience with this kind of things, I'd be very glad to read some suggestions.
I will keep the issue open till this kind of solution is found (or we gave up).
Thanks a lot for looking into this, @tjzel! I just added your code snippet to my Podfile
and noticed you forgot an end
in the last line. After updating the Podfile
and running pod install
I didn't get the shared transition running though. Maybe someone else can try it out in their app? @rockstar0711 ?
I followed instructions in this example https://reactnavigation.org/docs/shared-element-transitions/#minimal-example
My Podfile
require File.join(File.dirname(`node --print "require.resolve('expo/package.json')"`), "scripts/autolinking")
# Resolve react_native_pods.rb with node to allow for hoisting
require Pod::Executable.execute_command('node', ['-p',
'require.resolve(
"react-native/scripts/react_native_pods.rb",
{paths: [process.argv[1]]},
)', __dir__]).strip
platform :ios, '13.0'
prepare_react_native_project!
flipper_config = ENV['NO_FLIPPER'] == "1" ? FlipperConfiguration.disabled : FlipperConfiguration.enabled
linkage = ENV['USE_FRAMEWORKS']
if linkage != nil
Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green
use_frameworks! :linkage => linkage.to_sym
end
target 'weburn' do
pre_install do |installer|
installer.pod_targets.each do |pod|
if pod.name.eql?('RNScreens')
def pod.build_type
Pod::BuildType.static_library
end
end
end
end
use_expo_modules!
post_integrate do |installer|
begin
expo_patch_react_imports!(installer)
rescue => e
Pod::UI.warn e
end
end
config = use_native_modules!
# Firebase: https://rnfirebase.io/#altering-cocoapods-to-use-frameworks
use_frameworks! :linkage => :static
$RNFirebaseAsStaticFramework = true
# Flags change depending on the env values.
flags = get_default_flags()
use_react_native!(
:path => config[:reactNativePath],
# Hermes is now enabled by default. Disable by setting this flag to false.
:hermes_enabled => flags[:hermes_enabled],
:fabric_enabled => flags[:fabric_enabled],
# Enables Flipper.
#
# Note that if you have use_frameworks! enabled, Flipper will not work and
# you should disable the next line.
# :flipper_configuration => flipper_config,
# An absolute path to your application root.
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
target 'weburnTests' do
inherit! :complete
# Pods for testing
end
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
installer,
config[:reactNativePath],
:mac_catalyst_enabled => false
)
__apply_Xcode_12_5_M1_post_install_workaround(installer)
end
end
@brandtnewww Thanks for noticing the missing end
, I edited it 😅.
I used your Podfile with new RN App with all the required packages, using the example you linked, and everything was fine. The only thing I obviously had to change in the Podfile was:
diff
diff --git a/ios/Podfile.old b/ios/Podfile
index f2c4042..c35e833 100644
--- a/ios/Podfile.old
+++ b/ios/Podfile
@@ -16,7 +16,7 @@ if linkage != nil
use_frameworks! :linkage => linkage.to_sym
end
-target 'weburn' do
+target 'App' do
pre_install do |installer|
installer.pod_targets.each do |pod|
@@ -59,11 +59,6 @@ target 'weburn' do
:app_path => "#{Pod::Config.instance.installation_root}/.."
)
- target 'weburnTests' do
- inherit! :complete
- # Pods for testing
- end
-
post_install do |installer|
# https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L197-L202
react_native_post_install(
@tjzel I have the same problem, can you help me ? I used your Podfile too
For expo users:
I could solve it with @tjzel solution and turned it into an expo plugin gist
Legend!
@GusttavoCastilho Could you provide some more info about the problem you are still encountering?
@felippewick That's awesome!
For expo users:
I could solve it with @tjzel solution and turned it into an expo plugin gist
Is it still working for you? Getting an error when building on Expo 50
Error: [ios.dangerous]: withIosDangerousBaseMod: Failed to match " flags = get_default_flags()" in contents: require File.join(File.dirname(
node --print "require.resolve('expo/package.json')"), "scripts/autolinking") require File.join(File.dirname(
node --print "require.resolve('react-native/package.json')"), "scripts/react_native_pods")
@julian-gargicevich, I got the above Expo Config plugin working by changing the anchor
below to a line that is in my ios
Podfile on Expo 50.
- anchor: ' flags = get_default_flags()', // Seems the '...get_default_flags..' line isn't in the Podfile anymore(?).
+ anchor: ' post_install do |installer|',
Successfully seeing transitions now 🎉 (no patch-package etc required). Thank you @tjzel!
For Expo users who never installed Plugins before, here is how you do it.
You probably have app.json instead of app.config.js file.
- Create a file name called "app.config.js"
- Paste this code:
const { withPlugins } = require('expo/config-plugins')
const withReanimatedUseFrameworks = require('./withReanimatedUseFrameworks') // adjust the path if necessary
module.exports = ({ config }) => {
return withPlugins(
{
...config,
expo: {
...// the rest of your app.json
},
},
[withReanimatedUseFrameworks]
)
}
- Add the content of your app.json into the commented area and dont forget to DELETE your app.json file.
- Copy the plugin file that was provided above by the legends, and create a file "withReanimatedUseFrameworks.js" in your root directory.
That it is you should be all set to go, try building the app now, and it should work as expected.
Note: The animation transition still didn't work for me but it might actually work for you, I have a large project with so many dependencies with Firebase SDK + RN-firebase both installed, and other libraries as well. So I am still working on the solution.
For anyone trying to install the plugin following the method above and is finding that their podfile isn't being updated. Mine started working when I remove the expo object and replaced with the actual data. So replaced:
const { withPlugins } = require('expo/config-plugins')
const withReanimatedUseFrameworks = require('./withReanimatedUseFrameworks') // adjust the path if necessary
module.exports = ({ config }) => {
return withPlugins(
{
...config,
expo: {
name: "AppName",
slug: "AppSlug",
...
},
},
[withReanimatedUseFrameworks]
)
}
With
const { withPlugins } = require('expo/config-plugins')
const withReanimatedUseFrameworks = require('./withReanimatedUseFrameworks') // adjust the path if necessary
module.exports = ({ config }) => {
return withPlugins(
{
...config,
name: "AppName",
slug: "AppSlug",
...
},
[withReanimatedUseFrameworks]
)
}
FYI I was only able to get the config plugin to work with the following mergeContents
options so that it was under the correct target:
anchor: 'config = use_native_modules!',
offset: 2,
I finally had some time to dig into it, and here are the results.
What
The problem is not with Firebase itself, but the
Podfile
option it requires for the installation, as you have mentioned:
use_frameworks! :linkage => :static
Adding this line changes how linking is made and because of that the macro defined here resolves to
false
.This macro is a simple check if the user has
react-native-screens
installed (the header is accessible). If yes, then we use actual Shared Element Transitions implementation. If not, then we load a mock. So in this case, we incorrectly use the mock. "Duplicate shared tag" error happening here is just a coincidence - it doesn't have a mock (but it should have).From what I understand, this is happening because
react-native-screens
is not a dependency of Reanimated, and using dynamic workflows means it's unavailable (unaccessible) at compile-time, even though static linking is on.Solution
For the time being, I've found a workaround for it. All you need to do is to add the following to your
Podfile
:pre_install do |installer| installer.pod_targets.each do |pod| if pod.name.eql?('RNScreens') def pod.build_type Pod::BuildType.static_library end end end end
This will make
RNScreens
a static library instead of a dynamic workflow and from my testing everything was working fine.Notes
Unfortunately, we haven't yet found an elegant solution that wouldn't require additional input from the user (adding to
Podfile
). By elegant, I mean a way to find ifreact-native-screens
is installed without digging throughnode_modules
with some scripts or else. If someone has some experience with this kind of things, I'd be very glad to read some suggestions.I will keep the issue open till this kind of solution is found (or we gave up).
It is work a way
Has there been a more elegant fix to this issue?
just editing the podfile will not work since expo will regenerate that. Using a plugin somewhat works but also has been causing some unexpected behavior for me.
e.g. clicking r to reload the app breaks things again.
Hi @antochan. I will ask my colleagues from Expo about this issue and let you know!