From 6ff02e59c74ce257b914cf95905396002f9bddaf Mon Sep 17 00:00:00 2001 From: Chris Bobbe Date: Tue, 1 Sep 2020 10:51:27 -0700 Subject: [PATCH] flow: Use `typeof TextInput` when we want the type, not the value. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We add `typeof` in several places to address this Flow error that starts appearing at the RN and Flow upgrade: ``` Cannot use `TextInput` as a type. A name can be used as a type only if it refers to a type definition, an interface definition, or a class definition. To get the type of a non-class value, use `typeof`. ``` I'm not sure if this is due to the Flow upgrade or to changes React Native made to `TextInput`, or both. Several changes to `TextInput` are announced in the RN changelog [1], including three that are breaking, but I haven't been able to identify any in particular that would start giving us that error. With that dealt with, we also get this new error on calling various methods on the instance stored at a `TextInput` ref (e.g., `textInputRef.current.focus()`): ``` Cannot call textInputRef.current.focus because: • Either property focus is missing in AbstractComponent [1]. • Or property focus is missing in object type [2]. ``` At first, I thought something was wrong with how we're annotating the variable storing the ref, or that Flow didn't fully understand the `React.createRef` API (we started using that in a recent commit before the main upgrade commit). But rather, it seems to be an issue that's known to occur at RN v0.61.1, and which didn't occur on `master` as of 2020-04-06 [2]. Checking commits around that date in `react-native`, I'm pretty sure we'll have a fix in RN v0.63 (#4245). [1] https://github.com/react-native-community/releases/blob/master/CHANGELOG.md#0620 [2] See point 2 at https://github.com/facebook/react-native/issues/28459#issuecomment-609957836. --- src/common/Input.js | 6 +++--- src/common/InputWithClearButton.js | 8 ++++---- src/common/SmartUrlInput.js | 12 ++++++++---- src/compose/ComposeBox.js | 22 ++++++++++++---------- 4 files changed, 27 insertions(+), 21 deletions(-) diff --git a/src/common/Input.js b/src/common/Input.js index 1d145514f3e..dd9813309a5 100644 --- a/src/common/Input.js +++ b/src/common/Input.js @@ -8,10 +8,10 @@ import type { ThemeData } from '../styles'; import { ThemeContext, HALF_COLOR, BORDER_COLOR } from '../styles'; export type Props = $ReadOnly<{| - // TextInput's definition changes across the RN v0.61 -> v0.62 - // upgrade; we'll handle that change after the upgrade. + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 // $FlowFixMe - ...$PropertyType, + ...$PropertyType, placeholder: LocalizableText, onChangeText?: (text: string) => void, textInputRef?: React$Ref, diff --git a/src/common/InputWithClearButton.js b/src/common/InputWithClearButton.js index e5b332964d0..87bdeec86b4 100644 --- a/src/common/InputWithClearButton.js +++ b/src/common/InputWithClearButton.js @@ -32,10 +32,7 @@ export default class InputWithClearButton extends PureComponent { canBeCleared: false, text: '', }; - // TextInput's definition changes across the RN v0.61 -> v0.62 - // upgrade; we'll handle that change after the upgrade. - // $FlowFixMe - textInputRef = React.createRef(); + textInputRef = React.createRef(); handleChangeText = (text: string) => { this.setState({ @@ -50,6 +47,9 @@ export default class InputWithClearButton extends PureComponent { handleClear = () => { this.handleChangeText(''); if (this.textInputRef.current) { + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 + // $FlowFixMe this.textInputRef.current.clear(); } }; diff --git a/src/common/SmartUrlInput.js b/src/common/SmartUrlInput.js index 7ea87705070..67f8461adc5 100644 --- a/src/common/SmartUrlInput.js +++ b/src/common/SmartUrlInput.js @@ -66,15 +66,15 @@ export default class SmartUrlInput extends PureComponent { state = { value: '', }; - // TextInput's definition changes across the RN v0.61 -> v0.62 - // upgrade; we'll handle that change after the upgrade. - // $FlowFixMe - textInputRef = React.createRef(); + textInputRef = React.createRef(); focusListener: void | NavigationEventSubscription; componentDidMount() { this.focusListener = this.props.navigation.addListener('didFocus', () => { if (this.textInputRef.current) { + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 + // $FlowFixMe this.textInputRef.current.focus(); } }); @@ -96,9 +96,13 @@ export default class SmartUrlInput extends PureComponent { urlPress = () => { const { textInputRef } = this; if (textInputRef.current) { + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 + // $FlowFixMe textInputRef.current.blur(); setTimeout(() => { if (textInputRef.current) { + // $FlowFixMe - same as above textInputRef.current.focus(); } }, 100); diff --git a/src/compose/ComposeBox.js b/src/compose/ComposeBox.js index 469bf1d9f1a..d5cf2ca3f6d 100644 --- a/src/compose/ComposeBox.js +++ b/src/compose/ComposeBox.js @@ -106,16 +106,16 @@ function randomInt(min, max) { return Math.floor(Math.random() * (max - min + 1)) + min; } -// TextInput's definition changes across the RN v0.61 -> v0.62 -// upgrade; we'll handle that change after the upgrade. -// $FlowFixMe -export const updateTextInput = (textInput: TextInput | null, text: string): void => { +export const updateTextInput = (textInput: typeof TextInput | null, text: string): void => { if (textInput === null) { // Depending on the lifecycle events this function is called from, // this might not be set yet. return; } + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 + // $FlowFixMe textInput.setNativeProps({ text }); if (text.length === 0 && TextInputReset) { @@ -129,12 +129,8 @@ class ComposeBox extends PureComponent { static contextType = ThemeContext; context: ThemeData; - // TextInput's definition changes across the RN v0.61 -> v0.62 - // upgrade; we'll remove these fixmes after we take that upgrade. - // $FlowFixMe - messageInputRef = React.createRef(); - // $FlowFixMe - topicInputRef = React.createRef(); + messageInputRef = React.createRef(); + topicInputRef = React.createRef(); // TODO: Type-check this, once we've adjusted our `react-redux` // wrapper to do the right thing. It should be @@ -350,6 +346,9 @@ class ComposeBox extends PureComponent { } completeEditMessage(); if (this.messageInputRef.current !== null) { + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 + // $FlowFixMe this.messageInputRef.current.blur(); } }; @@ -364,6 +363,9 @@ class ComposeBox extends PureComponent { this.setMessageInputValue(message); this.setTopicInputValue(topic); if (this.messageInputRef.current !== null) { + // See point 2 at + // https://github.com/facebook/react-native/issues/28459#issuecomment-609957836 + // $FlowFixMe this.messageInputRef.current.focus(); } }