-
Notifications
You must be signed in to change notification settings - Fork 47.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add HostComponent type to ReactNative #16898
Conversation
@@ -161,7 +161,7 @@ export default function( | |||
measureLayout: function( | |||
relativeToNativeNode: number | Object, | |||
onSuccess: MeasureLayoutOnSuccessCallback, | |||
onFail: () => void /* currently unused */, | |||
onFail?: () => void /* currently unused */, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was always optional in the types used in React Native, but because the two types are duplicated in ReactNativeTypes
, they must have fallen out of sync.
@@ -151,9 +151,9 @@ class ReactFabricHostComponent { | |||
} | |||
|
|||
measureLayout( | |||
relativeToNativeNode: number | Object, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yay!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize it's not part of this change, but should the warningWithoutStack
inside of this function (and the one in packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
) be __DEV__
gated?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
warningWithoutStack internally has a dev check and is a no-op in dev.
@@ -8,7 +8,7 @@ | |||
* @flow | |||
*/ | |||
|
|||
import React from 'react'; | |||
import * as React from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is needed because we are now importing types from React. ElementRef
, and AbstractComponent
.
): void, | ||
setNativeProps(nativeProps: Object): void, | ||
}; | ||
|
||
export type NativeMethodsMixinType = NativeMethods; | ||
export type HostComponent<T> = React.AbstractComponent< |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So simple. So clean.
Summary: I upstreamed the changes to this file from previous commits to React in this (unlanded) PR: facebook/react#16898 (comment) I had to make some additional changes to be able to make Flow pass there. Bringing those changes back to FBSource as well. Having this change made here will make the next sync easier as we won't have to deal with conflicts then. Changelog: [Internal] Reviewed By: cpojer Differential Revision: D17586781 fbshipit-source-id: 4be8376d0af4fb5d63410afaaf5bb0005d992981
@@ -151,9 +151,9 @@ class ReactFabricHostComponent { | |||
} | |||
|
|||
measureLayout( | |||
relativeToNativeNode: number | Object, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realize it's not part of this change, but should the warningWithoutStack
inside of this function (and the one in packages/react-native-renderer/src/ReactNativeFiberHostComponent.js
) be __DEV__
gated?
relativeToNativeNode.canonical && | ||
relativeToNativeNode.canonical._nativeTag | ||
) { | ||
/* $FlowFixMe canonical doesn't exist on the node. | ||
I think this branch is dead and will remove it in a followup */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was wondering if the change from Object
-> ReactNativeFiberHostComponent
made sense given relativeToNativeNode.canonical
but I assume it's okay?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah.
When I added this option I wrote tests that called this with createClass, ReactNativeNativeComponent and a host component. Nothing triggers this branch. That's why I think this is dead.
Worst case, nothing except some of our Fabric screens are using this API yet and we'll get quick signal if I'm wrong once we delete it. But it's unrelated to this type change.
@@ -8,7 +8,7 @@ | |||
* @flow | |||
*/ | |||
|
|||
import React from 'react'; | |||
import React, {type ElementRef, type AbstractComponent} from 'react'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't know you could mix ES imports and type imports this way 😮
export type NativeMethodsMixinType = NativeMethods; | ||
export type HostComponent<T> = AbstractComponent< | ||
T, | ||
$ReadOnly<$Exact<NativeMethods>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think I understand the purpose of $ReadOnly
or $Exact
here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From @jbrown215:
Definitely consider making the instance type of HostComponent read-only-- all of those function names seem like things you don't want people to overwrite. If the object really has no other properties, you can also make it exact. If it might, don't, otherwise spreading that object would be unsound (not that I can see a reason why someone would want to spread it?)
* Add HostComponent type to ReactNative * Use type alias imports instead of wildcard * Fix forgotten Object in measureLayout type
Note: This change was already landed to React Native in facebook/react-native@69c38e5 so this commit just updates the types in React core to make the next sync not have conflicts.
In React Native there are three types of "Native" components.
The implementation for how to handle all three of these exists in the React Native Renderer. Refs attached to components created via these methods provide a set of functions such as
These methods have been used for our core components in the repo to provide a consistent API. Many of the APIs in React Native require a
reactTag
to a host component. This is acquired by callingfindNodeHandle
with any component.findNodeHandle
works with the first two approaches.For a lot of our new Fabric APIs, we will require passing a ref to a HostComponent directly instead of relying on
findNodeHandle
to tunnel through the component tree as that behavior isn't safe with React concurrent mode.The goal of this change is to enable us to differentiate between components created with
requireNativeComponent
and the other types. This will be needed to be able to safely type the new APIs.For existing components that should support being a host component but need to use some JS behavior in a wrapper, they should use
forwardRef
. The majority of React Native's core components were migrated to useforwardRef
last year. Components that can't use forwardRef will need to have a method likegetNativeRef()
to get access to the underlying host component ref.Note, we will need follow up changes as well as changes to the React Renderer in the React repo to fully utilize this new type.