2017-05-04 2 views
1

J'ai un comportement bizarre de mon "TextInput". Je suis en train de filtrer un ListView basé sur une entrée TextInput:OnChange déclenche seulement après 2 entrées de texte

export default class SearchTabScreen1 extends Component { 
    constructor(props) { 
    super(props); 
    this.state = { 
     searchText:'', 
     data:[] 
    }; 
} 

setSearchText(event) { 
    var reset = realm.objects('User'); 
    if (this.state.data !== reset){ 
    this.setState({ 
     data:realm.objects('User') 
    }); 

    const searchText = event.nativeEvent.text; 
    this.setState({searchText:searchText}); 
    console.log(this.state.searchText); 

    var searchString = this.state.searchText; 
    if(searchString != ""){ 
     let searchResult = realm.objects('User').filtered('name BEGINSWITH[c] $0', searchString); 
     var filteredData = searchResult; 

     this.setState({ 
     data : filteredData 
     }); 
     console.log("FILTERED", filteredData); 
    } 
    } 
} 

render() { 
     return (
     <View style={{flex: 1, padding: 20}}> 
      <TextInput 
      ref="recherche" 
      placeholder="Search" 
      autoCorrect={true} 
      returnKeyLabel="search" 
      underlineColorAndroid="black" 
      value = {this.state.searchText} 
      onChange={this.setSearchText.bind(this)} 
      /> 
      <ListViewDico 
      navigator={this.props.navigator} 
      dataFromParent={this.state.data} 
      /> 
     </View> 

Le problème est quand je tape un « L », par exemple, dans le TextInput le journal: console.log(this.state.searchText); montre rien.

Le journal n'affiche ce 'L' qu'après avoir tapé un deuxième caractère (quel qu'il soit) et ainsi de suite.

Je reçois toujours une réponse à un "t + 1 entrée".

J'apprécierais de l'aide, merci.

Répondre

1

La raison pour laquelle il arrive est que setState ne mute pas immédiatement l'état, mais prend du temps et que Javascript est votre async console.log() est exécuté avant que l'Etat a subi une mutation et donc vous ne recevez pas la valeur mise à jour, que lorsque il est exécuté la prochaine fois que vous voyez l'ancienne valeur. La solution consiste à appeler le console.log() dans le setState callback.

this.setState({searchText:searchText},() => { 
    console.log(this.state.searchText); 
}); 

code:

setSearchText(event) { 
    var reset = realm.objects('User'); 
    if (this.state.data !== reset){ 
    this.setState({ 
     data:realm.objects('User') 
    }); 

    const searchText = event.nativeEvent.text; 
    this.setState({searchText:searchText}, function() { 
     console.log(this.state.searchText); 
    }); 


    var searchString = searchText; 
    if(searchString != ""){ 
     let searchResult = realm.objects('User').filtered('name BEGINSWITH[c] $0', searchString); 
     var filteredData = searchResult; 

     this.setState({ 
     data : filteredData 
     }, function() { 
      console.log("FILTERED", filteredData); 
     }); 

    } 
    } 
} 
+0

Ouais j'oublié le setState! Mais cela affecte aussi mon interface: Quand je tape 'L', ma ListView ne se met pas à jour, mais après avoir tapé 'Lx' (ou autre chose comme 2 chahracters), tous les éléments commencent par 'L' dans ListView. Est-il possible de résoudre ce problème? –

+0

oui définitivement, cela arrive parce que la chaîne de recherche devrait être utilisée après la mise à jour de l'état, ou bien utiliser la valeur de 'event.native.text' –

+0

Ok ty! J'ai directement utilisé 'event.native.text' et ça fonctionne parfaitement maintenant. Je l'ai utilisé dans l'instruction if via la variable searchText. Mon filtre fonctionne bien maintenant :) Vraiment apprécier votre aide! –