Reputation: 168
I'm new to React Native and I've been working on a search bar that filters a list as the user types into the field. This is what it looks like...
<TextInput style={{width: '100%', textAlign: 'center'}}
ref={(ref) => this.searchInput = ref}
placeholder="Search"
onChangeText={ (text) => this.onChangeText(text)}
value={this.state.search} />
Here's the onChangeText method that I'm using for this behavior
onChangeText(text) {
var filtered;
this.setState({search: text});
filtered = this.props.data.filter((item) => {
if(item.section) {
return true;
}
return (item.label.toLowerCase().includes(text.toLowerCase()));
});
this.setState({filteredList: filtered});
}
Since it clears on render, I have set the state to persist whatever the user has typed into the search bar. This works fine, except the keyboard keeps closing every time the component re-renders (on every character the user inputs/deletes).
To try to fix that issue, I tried focusing on the input using refs like so
componentDidUpdate() {
if(this.searchInput) {
this.searchInput.focus();
}
}
But even so, the keyboard plays the open/close animation every now and then and doesn't handle the input/deletion smoothly.
To fix this issue, I was thinking of moving the TextInput into a separate component (with just that input field) and then adding that component to my list. However, I'll have to constantly pass the text data back to filter my list, adding more complexity. Is there perhaps a more straightforward solution to this?
Upvotes: 8
Views: 8190
Reputation: 31
An elegant solution to this problem is to NOT continually update the component's state when entering text, but rather update it on submission:
import React from 'react';
import { View } from 'react-native';
const MyComponent = () => {
let textValue;
function onFormSubmitted() {
// do something with textValue, update state
}
return (
<View>
<TextInput
onChangeText={(text) => {
textValue = text;
}}
onEndEditing={onFormSubmitted}
/>
</View>
);
};
export default MyComponent;
The reason for the flickering seems to be to be related to the component's size, and continuous updating of the state may work in small components, but it is wasteful in it's nature. If you're not dependent on real-time filtering of something, it should be completely unnecessary.
Upvotes: 3
Reputation: 121
I had the similar issue but I solved my problem by setting a number for the width of textInput. I am not sure if that related to this. But after I checked official docs, it says,
value
The value to show for the text input. TextInput is a controlled component, >which means the native value will be forced to match this value prop if >provided. For most uses, this works great, but in some cases this may cause >flickering - one common cause is preventing edits by keeping value the same. In >addition to simply setting the same value, either set editable={false}, or >set/update maxLength to prevent unwanted edits without flicker.
Good luck!
Upvotes: 3