May 22, 2026
Rebuilding a NewsFeed: Redux State Sync Across a Dozen Screens, and a React Native Upgrade Marathon
Over the past couple of months I’ve been deep in a NewsFeed rebuild for a React Native workplace communication app, alongside a parallel effort to drag the app’s React Native version forward by six minor releases. Two very different kinds of work, running at the same time, and both worth writing down.
The feature: more than just a list of posts
“NewsFeed” sounds simple until you look at how many places a single post actually has to live:
- The main feed, grouped by channel
- A pinned-posts screen
- A bookmarks screen
- A mentions screen
- An announcements screen
- A dedicated official-channel feed
The same post can appear in several of these at once. Reactions, comments, edits, pins, and bookmarks all had to be built from scratch — GroupedChannelPostsScreen, ReactionEmployeesModal, CreatePostModal, UpdatePostModal, comment threads with inline rich-text formatting, and an official channels system with its own delete/edit flows.
Channel groups got their own chunk of work too: a hierarchical department-tree selector for picking who’s in a channel, drag-based display-order changes for how groups are listed, and private/public toggling with the UI auto-expanding the right settings when a group is marked private.
The real problem: state, not UI
The hard part was never rendering a post — it was making sure that when you bookmark a post from the main feed, the same post’s bookmark icon updates instantly on the bookmarks screen, the pinned screen, and anywhere else it happens to be rendered, without every screen re-fetching from the API.
The fix was to stop treating each screen’s post list as its own local state and instead centralize post and interaction state in Redux, with every list subscribing to the same normalized store. A bookmark, pin, or edit dispatches one action; every connected screen re-renders from the same source of truth. It sounds obvious written down, but retrofitting that discipline onto a feed with six different views, after some of them already had their own ad hoc local state, was most of the actual engineering.
A few bugs from that process were good reminders of how subtle this stuff gets:
- A
RefreshControlcrash traced back to action creators dereferencingaction.payloadbefore checking it existed — the kind of bug that only shows up when a user pulls to refresh at exactly the wrong moment. - A comment section that kept firing the same API call in a loop, caused by an effect with the wrong dependency scope.
- Pin and bookmark icons quietly going stale on screens that weren’t subscribed to the same slice of state as the screen where the action happened.
None of these are exotic bugs. They’re the ordinary cost of building a feed that’s actually a dozen views sharing state, and they only get found by using the feature the way a real user would — tapping fast, pulling to refresh mid-load, jumping between screens.
The other project: React Native 0.70 → 0.76
Running in parallel, I took the app’s React Native version from 0.70 all the way to 0.76.7 — four incremental upgrades, each shipped as its own change, rather than one big jump. Jumping straight from 0.70 to 0.76 would have meant debugging a pile of compounding breakages with no way to isolate which version actually caused which problem. Going one minor version at a time meant each step’s official migration guide applied cleanly, and if something broke, it was obvious which upgrade broke it.
That work touched almost every layer of the native app:
- Migrated Android to the new
@react-native/gradle-pluginbuild system - Migrated iOS’s
AppDelegateto theRCTAppDelegatebase class - Enabled Hermes, while deliberately keeping the New Architecture disabled for stability
- Bumped the iOS deployment target and Podfile for the new engine’s C++20 requirement
- Fixed native module compatibility for a custom Android video view module that hadn’t been touched in years
- Replaced deprecated APIs like
Linking.removeEventListenerwith the newer subscription-based pattern along the way
Doing a feature build and a multi-version platform upgrade in the same stretch of time was a good lesson in scope discipline — the two efforts touched a lot of the same files, and keeping the feature work from getting tangled up in build-system churn (and vice versa) mattered more than either task individually.
What stuck with me
The feature work was a reminder that a “list of posts” is really a state-synchronization problem wearing a UI. The upgrade work was a reminder that boring, incremental steps beat big leaps when the alternative is debugging six versions’ worth of breaking changes at once. Neither insight is new, but both got relearned the hard way, which is usually how it goes.