Tried to register two views with the same name ProgressBarAndroid

Viewed 12639

Using react version 16.0.0 with react-native version 0.49.1 raises the red screen error "Tried to register two views with the same name ProgressBarAndroid". Removing all imports and instances of ProgressBarAndroid results in a well functioning program. Downgrading to react-native version 0.48.4 works as well. How do I use ProgressBarAndroid with the latest React Native version?

3 Answers

React Native starting from version 0.49 triggers this error if you are trying to call requireNativeComponent() for same component more than once. Even if they are called from different modules.

I had similar issue with custom view MyCustomView. So I just wrapped it in a single module:

// MyCustomView.js
import {requireNativeComponent} from 'react-native'
const MyCustomView = requireNativeComponent('MyCustomView', null)
export default MyCustomView

Though it might not be your exact case the root cause is the same.

import ReactNative  from 'react-native';

const description = Object.getOwnPropertyDescriptor( ReactNative, 'requireNativeComponent' )

if ( !description.writable ) {
  Object.defineProperty( ReactNative, 'requireNativeComponent', {
    value: (function () {
      const cache = {}
      const _requireNativeComponent = ReactNative.requireNativeComponent

      return function requireNativeComponent( nativeComponent ) {

        if ( !cache[ nativeComponent ] ) {
          cache[ nativeComponent ] = _requireNativeComponent( nativeComponent )
        }

        return cache[ nativeComponent ]
      }
    })(), writable: true
  } )
}

I experienced this during hot-reload in development. What causes the issue is the following: however JS is reloaded, the native code is still holding onto the same reference that it previously held onto. Whenever JS runs requireNativeComponent with the same viewName, it throws because the previous reference for the given viewName still exists. Here is the source file of requireNativeComponent, which clearly states that it should be memozied on the React Native side and only initialized once. Thus, the answer of @Teivaz is satisfying and no further hacking (like the answer of @蒋宏伟) is needed. If your code is structured well, you don't have to use any manual caching because your import structure solves it for you. :)

Related