callstack / react-native-builder-bob

👷‍♂️ Simple set of CLIs to scaffold and build React Native libraries for different targets
https://callstack.github.io/react-native-builder-bob/
2.75k stars 182 forks source link

Invariant Violation: Tried to register two views with the same name #370

Open venator85 opened 1 year ago

venator85 commented 1 year ago

Description

Steps to reproduce:

Actual: The error:

Invariant Violation: Tried to register two views with the same name TestView, js engine: hermes

is displayed in the console and in the Android app.

The error points to the requireNativeComponent line of the following code in src/index.tsx:

export const TestView =
  UIManager.getViewManagerConfig(ComponentName) != null
    ? requireNativeComponent<TestProps>(ComponentName)
    : () => {
        throw new Error(LINKING_ERROR);
      };

Expected: no errors should be shown.

Packages

Selected options

✔ What is the name of the npm package? … react-native-test ✔ What is the description for the package? … xxx ✔ What is the name of package author? … Alessio Bianchi ✔ What is the email address for the package author? … ✔ What is the URL for the package author? … ✔ What is the URL for the repository? … ✔ What type of library do you want to develop? › Native view ✔ Which languages do you want to use? › Kotlin & Swift ✔ Project created successfully at test!

Link to repro

No response

Environment

System:
    OS: macOS 13.2.1
    CPU: (8) arm64 Apple M2
    Memory: 102.70 MB / 24.00 GB
    Shell: 5.8.1 - /bin/zsh
  Binaries:
    Node: 19.7.0 - /opt/homebrew/bin/node
    Yarn: 1.22.19 - /opt/homebrew/bin/yarn
    npm: 9.5.0 - /opt/homebrew/bin/npm
    Watchman: 2023.03.06.00 - /opt/homebrew/bin/watchman
  Managers:
    CocoaPods: 1.12.0 - /opt/homebrew/bin/pod
  SDKs:
    iOS SDK:
      Platforms: DriverKit 22.2, iOS 16.2, macOS 13.1, tvOS 16.1, watchOS 9.1
    Android SDK: Not Found
  IDEs:
    Android Studio: 2022.1 AI-221.6008.13.2211.9619390
    Xcode: 14.2/14C18 - /usr/bin/xcodebuild
  Languages:
    Java: 11.0.18 - /usr/bin/javac
  npmPackages:
    @react-native-community/cli: Not Found
    react: 18.2.0 => 18.2.0 
    react-native: 0.71.4 => 0.71.4 
    react-native-macos: Not Found
  npmGlobalPackages:
    *react-native*: Not Found
atlj commented 1 year ago

It seems like whenever you trigger a refresh, this line gets called:

requireNativeComponent<TestProps>(ComponentName)

Forcing RN to load the same view twice.

My solution would be to extract this particular call into a separate file like this:

// TestView.tsx
import {
  requireNativeComponent,
  UIManager,
  Platform,
  ViewStyle,
} from 'react-native';

const LINKING_ERROR =
  `The package 'react-native-test' doesn't seem to be linked. Make sure: \n\n` +
  Platform.select({ ios: "- You have run 'pod install'\n", default: '' }) +
  '- You rebuilt the app after installing the package\n' +
  '- You are not using Expo Go\n';

type TestProps = {
  color: string;
  style: ViewStyle;
};

const ComponentName = 'TestView';

export const TestView =
  UIManager.getViewManagerConfig(ComponentName) != null
    ? requireNativeComponent<TestProps>(ComponentName)
    : () => {
      throw new Error(LINKING_ERROR);
    };
// index.tsx
export * from "./TestView"

And in theory, you won't have to touch TestView.tsx again and you can make as many changes you want to the index.tsx this way.

But I wonder if we should shape the template like this? @satya164

satya164 commented 1 year ago

@atlj sounds reasonable to me