Skip to content

Forking upstream files with react‐native‐platform‐override

Jon Thysell edited this page Sep 11, 2024 · 2 revisions

We often need to patch (or derive new files from) upstream react-native files in react-native-windows. As we're not a proper fork of react-native, we rely on a tool called react-native-platform-override to help us maintain our changes.

Patching an upstream JS file

Let's say we need to make some RNW-specific changes to an upstream RN file, either temporarily to unblock a build (until we can get the file fixed upstream) or something that wouldn't even make sense to submit an PR upstream for. To do that we're going to create an override file in the RNW repo that will replace the RN version.

RNW maintains the src-win folder to hold its overrides. Its structure mirrors the root structure of the upstream react-native package.

So for example, let's say we want to patch RN's Libraries/Pressability/HoverState.js file.

  1. First, copy the upstream file into the appropriate place in RNW's src-win folder. In this example, that would mean copying node_modules/react-native/Libraries/Pressability/HoverState.js to vnext/src-win/Libraries/Pressability/HoverState.js.
  2. Next, make you changes to that new file. Be sure to clearly mark your changes by surrounding code blocks with starting // [Windows and ending // Windows] comments. For this example, here we're adding a new else if clause to an if statement performing a platform check:
    +  // [Windows
    +} else if (Platform.OS === 'windows') {
    +  isEnabled = true;
    +  // Windows]
  3. Finally, we need to record the patched file by creating a new "override" using the react-native-platform-override command. From the vnext folder, run:
    yarn react-native-platform-override add src-win/Libraries/Pressability/HoverState.js
  4. When prompted, select the appropriate "override type". In this case, since we're patching an existing file, choose: Patches to upstream.
  5. When prompted, enter a GH issue number to track removing the patch (useful if the patch is only temporary while waiting for it to be merged upstream). For a "permanent" patch like in this example, simply enter 0.
  6. When prompted for the original file this override is based off of, you need to give the path of the upstream file including a prefix indicating which package it came from. In this example, overriding a react-native package, we'll prefix the relative path with packages/react-native, giving us: packages/react-native/Libraries/Pressability/HoverState.js.

There should now be a new entry in the vnext/overrides.json file. This will ensure that during integrations our tooling will keep this file up-to-date with upstream changes (while still maintaining our patches).

To test your changes, the final step is to run yarn build in the vnext folder to make sure the new override is applied locally. You may need to close and restart any Metro servers you have running to see the changes applied.

Creating a platform-specific version of an upstream JS file

Let's say we need to make a RNW-specific version of an upstream file. The Metro bundler allows you to create platform-specific modules by creating a new file with the platform's identifier at the end of the name. For example, let's say there's the upstream LogBoxInspectorCodeFrame.js and we want to create our own LogBoxInspectorCodeFrame.windows.js version.

The steps are almost entirely the same as for patching upstream JS files. First we'd want to copy the file from node_modules/react-native/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.js to vnext/src-win/Libraries/LogBox/UI/LogBoxInspectorCodeFrame.windows.js.

Continue with the steps above, the only difference is, when asked for the "override type", choose: Derived from upstream. This lets the tooling know that we're not just patching an existing file, we're providing a new file that is derived from it.