简体   繁体   English

在 UIManager 中找不到 requireNativeComponent

[英]requireNativeComponent was not found in UIManager

I know this question has been asked many times but all the questions refers to integrating a third party dependency in react-native app but in my case it is because of my own native code and I am having issues on how to fix it.我知道这个问题已经被问过很多次了,但是所有的问题都是指在react-native应用程序中集成第三方依赖项,但就我而言,这是因为我自己的本机代码,我在如何修复它时遇到了问题。 I am using react-native 0.69我正在使用react-native 0.69

Here is snippet of my code这是我的代码片段

CealScanQrView.kt

class CealScanQrView(context: Context): FrameLayout(context) {
...
//Contains all the logic of integrating camerax, check below code repo to see the full source code 
...
}

CealScanQrFragment.kt

class CealScanQrFragment: Fragment() {
    private lateinit var cealScanQrView: CealScanQrView

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
        super.onCreateView(inflater, container, savedInstanceState)
        cealScanQrView = CealScanQrView(requireNotNull(context))
        return cealScanQrView // this CustomView could be any view that you want to render
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        // do any logic that should happen in an `onCreate` method, e.g:
        cealScanQrView.setUpCamera(requireActivity())
    }

    override fun onDestroy() {
        super.onDestroy()
        cealScanQrView.destroyCamera()
    }
}


CealScanQrViewManager.kt

class CealScanQrViewManager(
    private val reactContext: ReactApplicationContext
) : ViewGroupManager<FrameLayout>() {

    private val cealScanQrView = "CealScanQrView"
    private val topChange = "topChange"
    private val phasedRegistrationNames = "phasedRegistrationNames"
    private val bubbled = "bubbled"
    private val onChange = "onChange"
    private val create = "create"

    companion object {
        private const val COMMAND_CREATE = 1
    }

    private var propWidth: Int? = null
    private var propHeight: Int? = null

    override fun getName() = cealScanQrView

    override fun createViewInstance(reactContext: ThemedReactContext) = FrameLayout(reactContext)

    override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE)

    override fun receiveCommand(root: FrameLayout, commandId: String?, args: ReadableArray?) {
        super.receiveCommand(root, commandId, args)
        val reactNativeViewId = requireNotNull(args).getInt(0)

        when (commandId?.toInt()) {
            COMMAND_CREATE -> createFragment(root, reactNativeViewId)
        }
    }

    private fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
        val parentView = root.findViewById<ViewGroup>(reactNativeViewId)
        setupLayout(parentView)

        val myFragment = CealScanQrFragment()
        val activity = reactContext.currentActivity as FragmentActivity
        activity.supportFragmentManager
            .beginTransaction()
            .replace(reactNativeViewId, myFragment, reactNativeViewId.toString())
            .commit()
    }

    private fun setupLayout(view: View) {
        Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
            override fun doFrame(frameTimeNanos: Long) {
                manuallyLayoutChildren(view)
                view.viewTreeObserver.dispatchOnGlobalLayout()
                Choreographer.getInstance().postFrameCallback(this)
            }
        })
    }

    @ReactPropGroup(names = ["width", "height"], customType = "Style")
    fun setStyle(view: FrameLayout, index: Int, value: Int) {
        if (index == 0) propWidth = value
        if (index == 1) propHeight = value
    }

    private fun manuallyLayoutChildren(view: View) {
        // propWidth and propHeight coming from react-native props
        val width = requireNotNull(propWidth)
        val height = requireNotNull(propHeight)

        view.measure(
            View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
            View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))

        view.layout(0, 0, width, height)
    }


    override fun getExportedCustomBubblingEventTypeConstants(): Map<String, Any> {
        return mapOf(
            topChange to mapOf(
                phasedRegistrationNames to mapOf(
                    bubbled to onChange
                )
            )
        )
    }
}

On the JS sideJS方面

I created a CealScanQrViewManager.tsx file我创建了一个CealScanQrViewManager.tsx文件

import {requireNativeComponent} from 'react-native';

export const CealScanQrViewManager = requireNativeComponent(
  'CealScanQrViewManager',
);

In App.tsx在 App.tsx 中

const createFragment = (viewId: number | null) =>
  UIManager.dispatchViewManagerCommand(
    viewId,
    // we are calling the 'create' command
    UIManager.CealScanQrViewManager.Commands.create.toString(),
    [viewId],
  );

const App = () => {
  const isDarkMode = useColorScheme() === 'dark';
  const [isCameraPermissionGranted, setIsCameraPermissionGranted] =
    useState(false);

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  const ref = useRef(null);

  useEffect(() => {
    requestCameraPermission();
  }, []);

  useEffect(() => {
    if (isCameraPermissionGranted) {
      const viewId = findNodeHandle(ref.current);
      createFragment(viewId);
    }
  }, [isCameraPermissionGranted]);

  const requestCameraPermission = async () => {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.CAMERA,
        {
          title: 'Cool Photo App Camera Permission',
          message:
            'Cool Photo App needs access to your camera ' +
            'so you can take awesome pictures.',
          buttonNeutral: 'Ask Me Later',
          buttonNegative: 'Cancel',
          buttonPositive: 'OK',
        },
      );
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        setIsCameraPermissionGranted(true);
      } else {
        console.log('Camera permission denied');
      }
    } catch (err) {
      console.warn(err);
    }
  };

  const readQr = async (data: any) => {
    console.log(data.nativeEvent.qrCode);
  };

  return (
    <SafeAreaView style={backgroundStyle}>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
      {isCameraPermissionGranted ? (
        <CealScanQrViewManager
          style={{
            // converts dpi to px, provide desired height
            height: PixelRatio.getPixelSizeForLayoutSize(200),
            // converts dpi to px, provide desired width
            width: PixelRatio.getPixelSizeForLayoutSize(200),
          }}
          ref={ref}
          onChange={readQr}
        />
      ) : (
        <View style={{flex: 1, backgroundColor: 'red'}} />
      )}
    </SafeAreaView>
  );
};

As soon as I grant the camera permission I get error saying一旦我授予相机权限,我就会收到错误消息

requireNativeComponent CealScanQrViewManager was not found in UIManager

在此处输入图像描述

Something of a stab-in-the-dark answer, but I think a correct one: the official guide to native components has you register a view manager, which is a class that overrides getName to return a fixed string, and then pass that same string to requireNativeComponent .有点刺眼的答案,但我认为一个正确的答案:本机组件的官方指南让您注册一个视图管理器,这是一个 class 覆盖getName以返回固定字符串,然后传递相同的字符串到requireNativeComponent

In the repository you linked, those names do not match.在您链接的存储库中,这些名称不匹配。 You requireNativeComponent('CealScanQrViewManager') , but register it as "CealScanQrView" .requireNativeComponent('CealScanQrViewManager') ,但将其注册为"CealScanQrView" As the official guide explains,正如官方指南解释的那样,

Name returned by getName is used to reference the native view type from JavaScript. getName返回的名称用于引用来自 JavaScript 的原生视图类型。

If the name does not match, no wonder looking up the type fails.如果名称不匹配,难怪查找类型失败。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 requireNativeComponent:在 UIManager 中找不到“RNSScreenStackHeaderConfig” - requireNativeComponent: "RNSScreenStackHeaderConfig" was not found in the UIManager 不变违规:requireNativeComponent:在 Android 的 UIManager 中找不到“RNSVGSvgViewAndroid” - Invariant Violation: requireNativeComponent: "RNSVGSvgViewAndroid" was not found in the UIManager in Android requireNativeComponent:运行 android 应用程序时,在 UIManager 中找不到“RNSScreenStackHeaderConfig” - requireNativeComponent: "RNSScreenStackHeaderConfig" was not found in the UIManager when running android app 不变违规:不变违规:requireNativeComponent:在 UIManager 中找不到“RNCSafeAreaView”。 - Invariant Violation: Invariant Violation: requireNativeComponent: "RNCSafeAreaView" was not found in the UIManager." React-Native-SVG 错误:不变违规:requireNativeComponent:在 UIManager 中找不到“RNSVGGroup” - React-Native-SVG Error: Invariant Violation: requireNativeComponent: "RNSVGGroup" was not found in the UIManager 在 UIManager 中找不到 RNCSafeAreaView - RNCSafeAreaView was not found in the UIManager 在 UIManager 中找不到“RNCSafeAreaView” - "RNCSafeAreaView" was not found in the UIManager 错误:在 UIManager 中找不到“ARTShape” - React native - Error : "ARTShape" was not found in the UIManager - React native 安装 React Native Map。 在 UIManager 中找不到 AIRMap - Installing React Native Map. AIRMap not found in UIManager 当我想使用 React Navigation 时出现错误,错误:requireNativeComponent:在 UIManger 中找不到“RNSScreen” - I get an error when I wanna use React Navigation, Error: requireNativeComponent: “RNSScreen” was not found in the UIManger
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM