I know this kind of question has been asked before but they are related to third party libraries, mine is related to requireNativeComponent
I have created a React Native
Component from a Native iOS
component
Here is my iOS
code
CanvasView
File
class CanvasView: UIView {
var lines = [[CGPoint]]()
override init(frame: CGRect) {
super.init(frame:frame)
backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 0)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
context.setStrokeColor(#colorLiteral(red: 0.9529411793, green: 0.6862745285, blue: 0.1333333403, alpha: 1))
context.setLineWidth(10)
context.setLineCap(.butt)
lines.forEach { (line) in
for(i,p) in line.enumerated() {
if i == 0 {
context.move(to: p)
} else {
context.addLine(to: p)
}
}
}
context.strokePath()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
lines.append([CGPoint]())
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: nil) else {
return
}
guard var lastLine = lines.popLast() else {return }
lastLine.append(point)
lines.append(lastLine)
setNeedsDisplay()
}
}
Canvas.swift
File
import Foundation
@objc(Canvas)
class Canvas: RCTViewManager {
override func view() -> UIView! {
return CanvasView()
}
override class func requiresMainQueueSetup() -> Bool {
return true
}
}
Canvas.m
file
#import <Foundation/Foundation.h>
#import "React/RCTViewManager.h"
@interface RCT_EXTERN_MODULE(Canvas, RCTViewManager)
@end
Here is my JS
code
const Canvas = requireNativeComponent('Canvas');
const App = () => {
return (
<View style={styles.container}>
<Canvas style={styles.bottom} />
</View>
);}
the code works fine, but even when I do some change in my react native code and do command+s to do fast refresh
I keep getting error saying Tried to register two views with the same name Canvas
, but when I run npx react-native run-ios
, the code works fine. So all in all hot reloading or fast refresh
is not supported when I include Native component created by me even though I am not changing the native component. I can understand if I change something in iOS swift or objective c code then I need to re-run npx react-native run-ios
but even after no changes in iOS
side and doing only changes in JS
side I keep getting this error. There are not two views with same name of Canvas
in my project. I also tried clearing watchman
, deleting package.json
and reinstalling npm
modules and pod
Same issue happens on android
side as well
When fast refresh runs, this line is executed again:
const Canvas = requireNativeComponent('Canvas');
And that's where the "Tried to register two views with same name" error comes from. There are a couple of ways to fix this.
export const Canvas = requireNativeComponent('Canvas');
, and then import it where you want to use it. You'll still get the same error if you save the new file that contains this line, but you typically won't change this file so it usually won't be an issue.requireNativeComponent
) multiple times. It's a bit ugly, but you can do this by storing it in the global scope: const Canvas = global['CanvasComponent'] || (global['CanvasComponent'] = requireNativeComponent('Canvas'));