Skip to content

Commit c1f9d15

Browse files
committed
Input, SmartUrlInput: Use modern React.createRef API.
Now that the `Input` component clearly doesn't use the ref on its child `TextInput` -- only `Input`'s consumers use it; see the previous commit -- we can straightforwardly use the new `React.createRef` API. We can also do so in `SmartUrlInput`. This will smoothen some necessary changes during the upcoming RN v0.61 -> v0.62 upgrade. In particular, it seems that the way `TextInput` is defined has changed in an interesting way (it certainly has changed), or else something happened in the Flow upgrade, to cause this error in several places where we use `TextInput` as a type: ``` 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 discovered, in this commit, that `React$Ref`, not `React$ElementRef`, seems to be the correct type for the `ref` attribute and the return value of `React.createRef`. Weeks ago, we used `React$RefElement` for `this.mentionWarnings` in `ComposeBox` and overlooked [1] the fact that it ended up being more or less completely un-typechecked, in 20bd98a. I'll add a TODO in the next commit, saying we should fix that. [1] #4101 (comment)
1 parent 0c57434 commit c1f9d15

File tree

4 files changed

+29
-37
lines changed

4 files changed

+29
-37
lines changed

src/common/Input.js

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export type Props = $ReadOnly<{|
1111
...$PropertyType<TextInput, 'props'>,
1212
placeholder: LocalizableText,
1313
onChangeText?: (text: string) => void,
14-
textInputRef?: (component: ?TextInput) => void,
14+
textInputRef?: React$Ref<typeof TextInput>,
1515
|}>;
1616

1717
type State = {|
@@ -87,11 +87,7 @@ export default class Input extends PureComponent<Props, State> {
8787
underlineColorAndroid={isFocused ? BORDER_COLOR : HALF_COLOR}
8888
onFocus={this.handleFocus}
8989
onBlur={this.handleBlur}
90-
ref={(component: ?TextInput) => {
91-
if (textInputRef) {
92-
textInputRef(component);
93-
}
94-
}}
90+
ref={textInputRef}
9591
{...restProps}
9692
/>
9793
)}

src/common/InputWithClearButton.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ export default class InputWithClearButton extends PureComponent<Props, State> {
3232
canBeCleared: false,
3333
text: '',
3434
};
35-
textInput: ?TextInput;
35+
textInputRef = React.createRef<TextInput>();
3636

3737
handleChangeText = (text: string) => {
3838
this.setState({
@@ -46,8 +46,8 @@ export default class InputWithClearButton extends PureComponent<Props, State> {
4646

4747
handleClear = () => {
4848
this.handleChangeText('');
49-
if (this.textInput) {
50-
this.textInput.clear();
49+
if (this.textInputRef.current) {
50+
this.textInputRef.current.clear();
5151
}
5252
};
5353

@@ -58,9 +58,7 @@ export default class InputWithClearButton extends PureComponent<Props, State> {
5858
<View style={styles.row}>
5959
<Input
6060
{...this.props}
61-
textInputRef={textInput => {
62-
this.textInput = textInput;
63-
}}
61+
textInputRef={this.textInputRef}
6462
onChangeText={this.handleChangeText}
6563
value={text}
6664
/>

src/common/SmartUrlInput.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,13 @@ export default class SmartUrlInput extends PureComponent<Props, State> {
6666
state = {
6767
value: '',
6868
};
69-
textInputRef: ?TextInput;
69+
textInputRef = React.createRef<TextInput>();
7070
focusListener: void | NavigationEventSubscription;
7171

7272
componentDidMount() {
7373
this.focusListener = this.props.navigation.addListener('didFocus', () => {
74-
if (this.textInputRef) {
75-
this.textInputRef.focus();
74+
if (this.textInputRef.current) {
75+
this.textInputRef.current.focus();
7676
}
7777
});
7878
}
@@ -92,9 +92,13 @@ export default class SmartUrlInput extends PureComponent<Props, State> {
9292

9393
urlPress = () => {
9494
const { textInputRef } = this;
95-
if (textInputRef) {
96-
textInputRef.blur();
97-
setTimeout(() => textInputRef.focus(), 100);
95+
if (textInputRef.current) {
96+
textInputRef.current.blur();
97+
setTimeout(() => {
98+
if (textInputRef.current) {
99+
textInputRef.current.focus();
100+
}
101+
}, 100);
98102
}
99103
};
100104

@@ -144,9 +148,7 @@ export default class SmartUrlInput extends PureComponent<Props, State> {
144148
underlineColorAndroid="transparent"
145149
onSubmitEditing={onSubmitEditing}
146150
enablesReturnKeyAutomatically={enablesReturnKeyAutomatically}
147-
ref={(component: TextInput | null) => {
148-
this.textInputRef = component;
149-
}}
151+
ref={this.textInputRef}
150152
/>
151153
{!value && this.renderPlaceholderPart(defaultOrganization)}
152154
{suffix !== null && this.renderPlaceholderPart(suffix)}

src/compose/ComposeBox.js

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,8 @@ function randomInt(min, max) {
105105
return Math.floor(Math.random() * (max - min + 1)) + min;
106106
}
107107

108-
export const updateTextInput = (textInput: ?TextInput, text: string): void => {
109-
if (!textInput) {
108+
export const updateTextInput = (textInput: TextInput | null, text: string): void => {
109+
if (textInput === null) {
110110
// Depending on the lifecycle events this function is called from,
111111
// this might not be set yet.
112112
return;
@@ -125,8 +125,8 @@ class ComposeBox extends PureComponent<Props, State> {
125125
static contextType = ThemeContext;
126126
context: ThemeData;
127127

128-
messageInput: ?TextInput = null;
129-
topicInput: ?TextInput = null;
128+
messageInputRef = React.createRef<TextInput>();
129+
topicInputRef = React.createRef<TextInput>();
130130
mentionWarnings: React$ElementRef<MentionWarnings> = React.createRef();
131131
inputBlurTimeoutId: ?TimeoutID = null;
132132

@@ -165,12 +165,12 @@ class ComposeBox extends PureComponent<Props, State> {
165165
};
166166

167167
setMessageInputValue = (message: string) => {
168-
updateTextInput(this.messageInput, message);
168+
updateTextInput(this.messageInputRef.current, message);
169169
this.handleMessageChange(message);
170170
};
171171

172172
setTopicInputValue = (topic: string) => {
173-
updateTextInput(this.topicInput, topic);
173+
updateTextInput(this.topicInputRef.current, topic);
174174
this.handleTopicChange(topic);
175175
};
176176

@@ -327,8 +327,8 @@ class ComposeBox extends PureComponent<Props, State> {
327327
});
328328
}
329329
completeEditMessage();
330-
if (this.messageInput) {
331-
this.messageInput.blur();
330+
if (this.messageInputRef.current !== null) {
331+
this.messageInputRef.current.blur();
332332
}
333333
};
334334

@@ -341,8 +341,8 @@ class ComposeBox extends PureComponent<Props, State> {
341341
const message = nextProps.editMessage ? nextProps.editMessage.content : '';
342342
this.setMessageInputValue(message);
343343
this.setTopicInputValue(topic);
344-
if (this.messageInput) {
345-
this.messageInput.focus();
344+
if (this.messageInputRef.current !== null) {
345+
this.messageInputRef.current.focus();
346346
}
347347
}
348348
}
@@ -454,9 +454,7 @@ class ComposeBox extends PureComponent<Props, State> {
454454
placeholder="Topic"
455455
defaultValue={topic}
456456
selectTextOnFocus
457-
textInputRef={component => {
458-
this.topicInput = component;
459-
}}
457+
textInputRef={this.topicInputRef}
460458
onChangeText={this.handleTopicChange}
461459
onFocus={this.handleTopicFocus}
462460
onBlur={this.handleTopicBlur}
@@ -472,9 +470,7 @@ class ComposeBox extends PureComponent<Props, State> {
472470
underlineColorAndroid="transparent"
473471
placeholder={placeholder}
474472
defaultValue={message}
475-
textInputRef={component => {
476-
this.messageInput = component;
477-
}}
473+
textInputRef={this.messageInputRef}
478474
onBlur={this.handleMessageBlur}
479475
onChangeText={this.handleMessageChange}
480476
onFocus={this.handleMessageFocus}

0 commit comments

Comments
 (0)