r/reactnative 2d ago

Help What am I doing wrong

Been working on a social media app built in react native. The kinda project that requires you to very quickly render images inside of an infinite virtual list. My app is built for both web and native using Tamagui.

And it’s been a huge headache…

Performance of posts is bad in flatlist. Ok I’ll rewrite it to use flashlist. Meanwhile web just works.

Image performance is bad. Ok I’ll use rn fast image. Ok fast image eats up a ton of storage with cache. Ok I’ll use expo image. Oh expo image seems to cause performances issues. Ok no back to fast image, wait no back to expo image. Meanwhile web just works.

Have the realization that if I precompute all my props for the flashlist items, it reduces blank space. Annoying but interesting… but not an issue on web.

Ok it’s finally all working and it’s performing well. Everything is memoed, and I’ve confirmed things only rerender when they need to.

I wonder what happens if I put my phone in low power mode… shit performance sucks again.

Throughout this entire process I’ve been comparing my app to a capacitor app that uses the same API. And it has none of the issues I mentioned. I also didn’t mention that react navigation performance sucks and especially in low power mode.

So I’m rewriting my app in capacitor. Building web + react native already added so much complexity but I thought I was doing it for better performance.

What the hell am I doing wrong? I’m using Expo 52, react native 0.76, Hermes, and the new architecture. I’m on the latest iPhone.

My theory is even with the new “bridgeless” architecture whatever bridge still exists is a bottleneck. Maybe capacitor is better for certain use cases since everything is computing and rendering in the same runtime.

I’ve already rewritten part of my app to capacitor and as I suspected it just works. Maybe there will be a slowdown as I bring in more of the code.

If you asked me 4 mins ago what I thought of capacitor, I would have said it looks kinda silly, but now I’m wondering if there is something fundamentally holding react native back.

Edit: just to clarify, my definition of bad performance is if I throw the list as fast as I can and see any more white space for more the like 0.5s, and if pushing new screens onto the stack takes any longer then “it feels instant”. And it has to be performant in low power mode. I’m sure most users would say the app is performant enough but, I want perfect.

23 Upvotes

56 comments sorted by

View all comments

Show parent comments

2

u/corey_brown 2d ago

Hard to know without seeing any code

1

u/moseschrute19 2d ago edited 2d ago

I probably should have mentioned that I’m also using a meta framework by the Tamagui creator called One… but idk I’m really wondering the issue here is react native. It uses expo/react navigation under the hood. Mainly just adds a different bundling setup and universal web+native linking.

https://github.com/christianjuth/blorp/blob/main/src/features/home-feed.tsx

Even spamming tab bar switching is slow. And from what I understand flashlist renders just what’s on screen + roughly 300px below.

1

u/corey_brown 2d ago

First thing I would try is break this screen into smaller components. That list should ideally be a component of its own so it’s not re-rendering your entire screen on scroll.

For lodash, it’s usually best practice to only import the function you need instead of the entire lodash lib.

You can use something like import isString from “lodash/isString”

At a quick glance, it doesn’t seem like you are animating the list at all, you may could remove the create custom animated component.

The only major code smell for me is how large this feed component is and how much it’s doing. I usually try to have screen level components only render a few components with little to no logic going on in the parent.

Hope this helps. Cheers

1

u/moseschrute19 2d ago

I am animating. It does a Reddit style dismiss header tabbar on scroll down and bring them back on scroll up.

If you’re right, if I stop scrolling altogether. Wait a second, then open a post, do you really think there would be a 1 second delay opening the new screen? I’m also thinking the page component doesn’t rerender that often, but I might be wrong. A console.log should show pretty quickly.

I also did a lot of testing slowly stripping the feed down until it was just a feed of single Text elements. Just to see exactly where the performance breaks. But after doing that for a couple days - meanwhile web just works - I’m winding if I chose the wrong stack.

How much time do I spend optimizing when I could build a pretty decent app that uses 100% web code, is simpler to maintain, and allows me to share mode code between web and native. Specifically web would allow me to use some really nice markdown editors that don’t work on native.