Skip to content

Commit 956ffd6

Browse files
authored
feat: print an error when library is not linked (#202)
We should show better error messages when the library is not linked than the cryptic `"BlaBlaView" was not found in the UIManager` or `Native module cannot be null` error messages.
1 parent ecea932 commit 956ffd6

File tree

7 files changed

+93
-77
lines changed

7 files changed

+93
-77
lines changed

packages/create-react-native-library/src/index.ts

Lines changed: 27 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ import validateNpmPackage from 'validate-npm-package-name';
99
import githubUsername from 'github-username';
1010
import prompts, { PromptObject } from './utils/prompts';
1111

12+
const FALLBACK_BOB_VERSION = '0.18.0';
13+
1214
const BINARIES = /(gradlew|\.(jar|keystore|png|jpg|gif))$/;
1315

1416
const COMMON_FILES = path.resolve(__dirname, '../templates/common');
@@ -21,46 +23,29 @@ const NATIVE_COMMON_FILES = path.resolve(
2123
'../templates/native-common'
2224
);
2325

24-
const FALLBACK_BOB_VERSION = '0.18.0';
26+
const NATIVE_FILES = {
27+
module: path.resolve(__dirname, '../templates/native-library'),
28+
view: path.resolve(__dirname, '../templates/native-view-library'),
29+
};
2530

26-
// Java
27-
const JAVA_FILES = (moduleType: ModuleType) => {
28-
switch (moduleType) {
29-
case 'module':
30-
return path.resolve(__dirname, '../templates/java-library');
31-
case 'view':
32-
return path.resolve(__dirname, '../templates/java-view-library');
33-
}
31+
const JAVA_FILES = {
32+
module: path.resolve(__dirname, '../templates/java-library'),
33+
view: path.resolve(__dirname, '../templates/java-view-library'),
3434
};
3535

36-
// Objc
37-
const OBJC_FILES = (moduleType: ModuleType) => {
38-
switch (moduleType) {
39-
case 'module':
40-
return path.resolve(__dirname, '../templates/objc-library');
41-
case 'view':
42-
return path.resolve(__dirname, '../templates/objc-view-library');
43-
}
36+
const OBJC_FILES = {
37+
module: path.resolve(__dirname, '../templates/objc-library'),
38+
view: path.resolve(__dirname, '../templates/objc-view-library'),
4439
};
4540

46-
// Kotlin
47-
const KOTLIN_FILES = (moduleType: ModuleType) => {
48-
switch (moduleType) {
49-
case 'module':
50-
return path.resolve(__dirname, '../templates/kotlin-library');
51-
case 'view':
52-
return path.resolve(__dirname, '../templates/kotlin-view-library');
53-
}
41+
const KOTLIN_FILES = {
42+
module: path.resolve(__dirname, '../templates/kotlin-library'),
43+
view: path.resolve(__dirname, '../templates/kotlin-view-library'),
5444
};
5545

56-
// Swift
57-
const SWIFT_FILES = (moduleType: ModuleType) => {
58-
switch (moduleType) {
59-
case 'module':
60-
return path.resolve(__dirname, '../templates/swift-library');
61-
case 'view':
62-
return path.resolve(__dirname, '../templates/swift-view-library');
63-
}
46+
const SWIFT_FILES = {
47+
module: path.resolve(__dirname, '../templates/swift-library'),
48+
view: path.resolve(__dirname, '../templates/swift-view-library'),
6449
};
6550

6651
type ArgName =
@@ -74,8 +59,6 @@ type ArgName =
7459
| 'type'
7560
| 'example';
7661

77-
type ModuleType = 'module' | 'view';
78-
7962
type Answers = {
8063
slug: string;
8164
description: string;
@@ -416,23 +399,24 @@ async function create(argv: yargs.Arguments<any>) {
416399
);
417400

418401
await copyDir(NATIVE_COMMON_FILES, folder);
402+
await copyDir(NATIVE_FILES[type], folder);
419403

420404
if (options.project.swift) {
421-
await copyDir(SWIFT_FILES(type), folder);
405+
await copyDir(SWIFT_FILES[type], folder);
422406
} else {
423-
await copyDir(OBJC_FILES(type), folder);
407+
await copyDir(OBJC_FILES[type], folder);
408+
}
409+
410+
if (options.project.kotlin) {
411+
await copyDir(KOTLIN_FILES[type], folder);
412+
} else {
413+
await copyDir(JAVA_FILES[type], folder);
424414
}
425415

426416
if (options.project.cpp) {
427417
await copyDir(CPP_FILES, folder);
428418
await fs.remove(path.join(folder, 'ios', `${options.project.name}.m`));
429419
}
430-
431-
if (options.project.kotlin) {
432-
await copyDir(KOTLIN_FILES(type), folder);
433-
} else {
434-
await copyDir(JAVA_FILES(type), folder);
435-
}
436420
}
437421

438422
try {

packages/create-react-native-library/templates/common/README.md

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,23 @@ npm install <%- project.slug %>
1010

1111
## Usage
1212

13+
<% if (project.moduleType === "view") { -%>
1314
```js
14-
import <%- project.name %> from "<%- project.slug %>";
15+
import { <%- project.name %>View } from "<%- project.slug %>";
1516

1617
// ...
1718

18-
const result = await <%- project.name %>.multiply(3, 7);
19+
<<%- project.name %>View color="tomato" />
1920
```
21+
<% } else { -%>
22+
```js
23+
import { multiply } from "<%- project.slug %>";
24+
25+
// ...
26+
27+
const result = await multiply(3, 7);
28+
```
29+
<% } -%>
2030

2131
## Contributing
2232

packages/create-react-native-library/templates/common/example/src/App.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@ import * as React from 'react';
22

33
<% if (project.moduleType === "view") { -%>
44
import { StyleSheet, View } from 'react-native';
5-
import <%- project.name %>ViewManager from '<%- project.slug %>';
5+
import { <%- project.name %>View } from '<%- project.slug %>';
66
<% } else { -%>
77
import { StyleSheet, View, Text } from 'react-native';
8-
import <%- project.name %> from '<%- project.slug %>';
8+
import { multiply } from '<%- project.slug %>';
99
<% } -%>
1010

1111
<% if (project.moduleType === "view") { -%>
@@ -21,7 +21,7 @@ export default function App() {
2121
const [result, setResult] = React.useState<number | undefined>();
2222

2323
React.useEffect(() => {
24-
<%- project.name %>.multiply(3, 7).then(setResult);
24+
multiply(3, 7).then(setResult);
2525
}, []);
2626

2727
return (
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
export default {
2-
multiply(a: number, b: number) {
3-
return Promise.resolve(a * b);
4-
},
5-
};
1+
export function multiply(a: number, b: number): Promise<number> {
2+
return Promise.resolve(a * b);
3+
}

packages/create-react-native-library/templates/native-common/src/index.tsx

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { NativeModules, Platform } from 'react-native';
2+
3+
const LINKING_ERROR =
4+
`The package '<%- project.slug %>' doesn't seem to be linked. Make sure: \n\n` +
5+
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
6+
'- You rebuilt the app after installing the package\n' +
7+
'- You are not using Expo managed workflow\n';
8+
9+
const <%- project.name %> = NativeModules.<%- project.name %>
10+
? NativeModules.<%- project.name %>
11+
: new Proxy(
12+
{},
13+
{
14+
get() {
15+
throw new Error(LINKING_ERROR);
16+
},
17+
}
18+
);
19+
20+
export function multiply(a: number, b: number): Promise<number> {
21+
return <%- project.name %>.multiply(a, b);
22+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import {
2+
requireNativeComponent,
3+
UIManager,
4+
Platform,
5+
ViewStyle,
6+
} from 'react-native';
7+
8+
const LINKING_ERROR =
9+
`The package '<%- project.slug %>' doesn't seem to be linked. Make sure: \n\n` +
10+
Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
11+
'- You rebuilt the app after installing the package\n' +
12+
'- You are not using Expo managed workflow\n';
13+
14+
type <%- project.name %>Props = {
15+
color: string;
16+
style: ViewStyle;
17+
};
18+
19+
const ComponentName = '<%- project.name %>View';
20+
21+
export const <%- project.name %>View =
22+
UIManager.getViewManagerConfig(ComponentName) != null
23+
? requireNativeComponent<<%- project.name %>Props>(ComponentName)
24+
: () => {
25+
throw new Error(LINKING_ERROR);
26+
};

0 commit comments

Comments
 (0)