Skip to content

Commit 3bf7064

Browse files
authored
chore: Run the fabric example on gesture-handler v3 (#582)
Stacked on #573. The fabric example targets the New Architecture, so this points it at gesture-handler v3 (which drops Old Architecture support) while the paper example stays on v2. It gives the repo a working v3 example on the New Architecture. Because the two examples now use different gesture-handler majors, two resolution fixes are needed, both scoped to the fabric example: - `react-native.config.js` resolves gesture-handler from the fabric app's own dependency (hoisted to the monorepo root). The shared `getDependencies` resolver points a differing-version dep at a local `node_modules` path that does not exist once v3 is hoisted, which silently drops the native module from autolinking. - `metro.config.js` blocks the v2 copy nested under the shared example app so the JS bundle resolves the same v3 the native build links against. Verified on an Android emulator (New Architecture): the full example app builds, runs, and reorders via drag-and-drop on gesture-handler v3, and the paper example's v2 resolution is unchanged.
1 parent c70a14f commit 3bf7064

6 files changed

Lines changed: 70 additions & 41 deletions

File tree

example/app/jest.config.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,22 @@
1+
import path from 'path';
12
import { type JestConfigWithTsJest, pathsToModuleNameMapper } from 'ts-jest';
23

34
import { compilerOptions } from './tsconfig.json';
45

6+
// react-native-sortables imports gesture-handler too, so it and the app must
7+
// resolve the same copy for one jest mock to cover both. Resolve this app's own
8+
// version (v2, which `jestSetup` mocks) hoist-proof via require.resolve: it finds
9+
// v2 whether it sits in this app's node_modules or the hoisted monorepo root, and
10+
// never the v3 copy the fabric example pins.
11+
const gestureHandlerPath = path
12+
.dirname(
13+
require.resolve('react-native-gesture-handler/package.json', {
14+
paths: [__dirname]
15+
})
16+
)
17+
.split(path.sep)
18+
.join('/');
19+
520
const config: JestConfigWithTsJest = {
621
clearMocks: true,
722
fakeTimers: {
@@ -13,10 +28,7 @@ const config: JestConfigWithTsJest = {
1328
...pathsToModuleNameMapper(compilerOptions.paths ?? {}, {
1429
prefix: '<rootDir>/'
1530
}),
16-
// react-native-sortables is built against gesture-handler v3, but the app's
17-
// jest mock targets v2; pin every import to the single mocked instance.
18-
'^react-native-gesture-handler$':
19-
'<rootDir>/../../node_modules/react-native-gesture-handler'
31+
'^react-native-gesture-handler$': gestureHandlerPath
2032
},
2133
preset: '@react-native/jest-preset',
2234
resolver: 'react-native-worklets/jest/resolver.js',

example/app/scripts/dependencies.js

Lines changed: 25 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,41 +1,38 @@
11
const path = require('path');
22

3+
const commonAppDir = path.resolve(__dirname, '..');
4+
5+
// Resolve where a dependency actually lives from an app's perspective - its own
6+
// node_modules, or the monorepo root once yarn hoists it. Using `require.resolve`
7+
// is hoist-proof, so an app that pins a divergent major (e.g. gesture-handler v3
8+
// in the fabric example) autolinks that version rather than a guessed path.
9+
function getRootPath(moduleName, currentAppDir) {
10+
try {
11+
return path.dirname(
12+
require.resolve(`${moduleName}/package.json`, {
13+
paths: [currentAppDir, commonAppDir]
14+
})
15+
);
16+
} catch {
17+
return path.resolve(currentAppDir, `../../node_modules/${moduleName}`);
18+
}
19+
}
20+
321
function getDependencies(currentAppDir = '.', excludeCommon = []) {
4-
const commonAppDir = path.resolve(__dirname, '..');
522
const commonAppPkg = require(path.resolve(commonAppDir, 'package.json'));
623
const currentAppPkg = require(path.resolve(currentAppDir, 'package.json'));
724

8-
const excludedCommonDeps = new Set(excludeCommon);
9-
10-
const allDeps = new Set([
11-
...[
12-
...Object.keys(commonAppPkg.dependencies ?? {}),
13-
...Object.keys(commonAppPkg.devDependencies ?? {})
14-
].filter(dep => !excludedCommonDeps.has(dep)),
25+
const excluded = new Set(excludeCommon);
26+
const names = [
27+
...Object.keys(commonAppPkg.dependencies ?? {}),
28+
...Object.keys(commonAppPkg.devDependencies ?? {}),
1529
...Object.keys(currentAppPkg.dependencies ?? {}),
1630
...Object.keys(currentAppPkg.devDependencies ?? {})
17-
]);
31+
].filter(name => !excluded.has(name));
1832

1933
const result = {};
20-
21-
for (const dep of allDeps) {
22-
// Find versions in both package.json files
23-
const commonVersion =
24-
commonAppPkg.dependencies?.[dep] ?? commonAppPkg.devDependencies?.[dep];
25-
const currentVersion =
26-
currentAppPkg.dependencies?.[dep] ?? currentAppPkg.devDependencies?.[dep];
27-
28-
if (!commonVersion || !currentVersion || commonVersion === currentVersion) {
29-
result[dep] = {
30-
root: path.resolve(currentAppDir, `../../node_modules/${dep}`)
31-
};
32-
} else {
33-
// Include from the local node_modules only if the dependency is present
34-
// in the current app and versions are different
35-
result[dep] = {
36-
root: path.resolve(currentAppDir, `node_modules/${dep}`)
37-
};
38-
}
34+
for (const name of new Set(names)) {
35+
result[name] = { root: getRootPath(name, currentAppDir) };
3936
}
4037

4138
return result;

example/app/scripts/metro.js

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,12 @@ const {
44
wrapWithReanimatedMetroConfig
55
} = require('react-native-reanimated/metro-config');
66

7+
function blockDir(dir) {
8+
return new RegExp(`^${escape(dir + path.sep)}.*$`);
9+
}
10+
711
function createMetroConfig(defaultConfig, currentAppDir, options = {}) {
8-
const { excludeFromRoot = [] } = options;
12+
const { excludeFromRoot = [], filterFromCommonApp = [] } = options;
913

1014
const monorepoRoot = path.resolve(currentAppDir, '../..');
1115

@@ -38,13 +42,23 @@ function createMetroConfig(defaultConfig, currentAppDir, options = {}) {
3842

3943
config.resolver.disableHierarchicalLookup = true;
4044

41-
if (excludeFromRoot.length > 0) {
42-
config.resolver.blockList = excludeFromRoot.map(
43-
m =>
44-
new RegExp(
45-
`^${escape(path.join(monorepoRoot, 'node_modules', m))}\\/.*$`
46-
)
47-
);
45+
const commonAppNodeModules = path.resolve(
46+
currentAppDir,
47+
'../app/node_modules'
48+
);
49+
const blockList = [
50+
...excludeFromRoot.map(m =>
51+
blockDir(path.join(monorepoRoot, 'node_modules', m))
52+
),
53+
// A host app can pin a divergent major of a shared dependency (e.g. the
54+
// fabric example on gesture-handler v3). Block the common app's copy so the
55+
// bundle resolves the host's own version, matching what the native build links.
56+
...filterFromCommonApp.map(m =>
57+
blockDir(path.join(commonAppNodeModules, m))
58+
)
59+
];
60+
if (blockList.length > 0) {
61+
config.resolver.blockList = blockList;
4862
}
4963

5064
return wrapWithReanimatedMetroConfig(config);

example/fabric/metro.config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,8 @@ const { createMetroConfig } = require('../app/scripts/metro');
33

44
const defaultConfig = getDefaultConfig(__dirname);
55

6-
module.exports = createMetroConfig(defaultConfig, __dirname);
6+
module.exports = createMetroConfig(defaultConfig, __dirname, {
7+
// This example runs gesture-handler v3; resolve it from this app rather than
8+
// the v2 copy pinned by the shared example app.
9+
filterFromCommonApp: ['react-native-gesture-handler']
10+
});

example/fabric/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"version": "1.0.0",
44
"dependencies": {
55
"react-native": "0.85.3",
6+
"react-native-gesture-handler": "3.0.2",
67
"react-native-sortables": "workspace:*"
78
},
89
"installConfig": {

yarn.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8499,6 +8499,7 @@ __metadata:
84998499
resolution: "example-fabric@workspace:example/fabric"
85008500
dependencies:
85018501
react-native: "npm:0.85.3"
8502+
react-native-gesture-handler: "npm:3.0.2"
85028503
react-native-sortables: "workspace:*"
85038504
languageName: unknown
85048505
linkType: soft

0 commit comments

Comments
 (0)