2017-06-21 5 views
9

Ich versuche, einen Statuswert für jeden Texteintrag in jeder Zeile meiner ListView festgelegt.React Native ListView TextInput stürzt von Leistungsoptimierung Rendering

Das Problem ist, dass React Native ListView Component hat eine Reihe von Optimierungstechniken wie das Entfernen von Zeilen, die außerhalb der Bildschirmgrenzen sind. Dies verursacht ein Problem, da die TextInputs ihre Werteigenschaft sperren, deren Bearbeitung nicht länger Änderungen widerspiegelt und der Zustandswert blockiert oder so etwas. Ich habe ein Video angehängt, um dieses Verhalten zu zeigen.

https://www.youtube.com/watch?v=fq7ITtzRvg4&feature=youtu.be

_renderRow(value){ 
    let tempWidth = window.width/2.13 
    if(value.data.length == 1){ 
     tempWidth = window.width*0.970 
    } 
    var Images = value.data.map((b,i) => { 
     let source = { uri: BUCKETIMAGES+'/'+b.image_filename} 
     return (
      <TouchableOpacity key={i} style={styles.cardImage}> 
       {b.profile_picture && 
       <View style={{zIndex: 4, width:31,height:31,borderWidth:1,borderColor:"#ccc",borderRadius:20, position: "absolute", right: -6, top: -6}}> 
        <CacheableImage style={{width:30,height:30,borderWidth:3,borderColor:"white",borderRadius:15,position: "absolute", right: 0, top: 0}} source={{uri: BUCKETIMAGES+'/'+b.profile_picture}}/> 
       </View> 
       } 
       <CacheableImage source={source} style={{height: 150, width: tempWidth}}/> 
      </TouchableOpacity> 
     ) 
    }); 
    return(
      <View key={value.id} style={styles.statusContainer}> 
       <View style={[styles.statusHeader,{height: 50, alignItems: "center"}]}> 
        <View style={{flex:0.85}}> 
          <View style={{flexDirection: "row"}}> 
           <Text style={{color: "#666666", fontWeight: "bold", fontSize: 18, paddingLeft: 20}}>Team {value.type}</Text> 
          </View> 
          <Text style={{color: "grey", fontSize: 15, paddingLeft: 20, paddingRight: 20}}>{value.date}</Text> 
        </View> 
        <View style={{flex:0.15,height: 20, justifyContent: "center",width: 30}}> 
          <Icon name="ios-more" type="ionicon" size={40} color="#a9a9a9" /> 
        </View> 
       </View> 
       <View style={{flexDirection: "row", flexWrap: "wrap"}}> 
        { Images } 
       </View> 
       <View style={{zIndex: 10}}> 

       </View> 
       <View style={[styles.commentHeader,{height: 30,flex:0.8, zIndex: 5}]}> 
        <View style={{height: 30, width: 40}}> 
          <Icon name="ios-chatboxes-outline" type="ionicon" size={30} color="grey" /> 
        </View> 
        <View style={{flex:0.9}}> 
          <TextInput 
           style={styles.commentInput} 
           placeholder="Say something..." 
           placeholderTextColor="gray" 
           underlineColorAndroid="transparent" 
           multiline={true} 
           blurOnSubmit={true} 
           value={this.state['comment'+value.id]} 
           onChangeText={(commentInput) => {this.setState({["comment"+value.id]: commentInput})}} 
          /> 
        </View> 
        <View style={{justifyContent: "center", marginRight: 20}}> 
         <TouchableOpacity onPress={() => {this.setState({commentID: value.id}, this.addComment)}}> 
          <Icon name="md-send" type="ionicon" size={25} color="#CCC" /> 
         </TouchableOpacity> 
        </View> 
       </View>  
      </View> 
    ) 
} 

render() { 
    return(
     <View style={styles.container}> 
      {Platform.OS === "ios" && 
      <View style={styles.statusBar}></View> 
      } 
      {this.state.loading && 
      <ActivityIndicator 
       animating={true} 
       color="#E91E63" 
       size="large" 
       style={{marginTop: 80}} 
      /> 
      } 
      {!this.state.loading && 
      <ListView 
        dataSource = {this.state.dataSource} 
        renderRow = {this._renderRow.bind(this)} 
        initialListSize={10} 
        enableEmptySections={true} 
      />} 
     </View> 
    ) 
} 
+0

Versuchen Sie, FlatList zu verwenden, wenn Sie eine ausreichend aktuelle Version von reactive-native haben. http://facebook.github.io/react-native/blog/2017/03/13/better-list-views.html "Keine ListViews oder DataSources mehr, veraltete Zeilen" –

Antwort

5

Ich würde empfehlen, Erstellen einer Komponente jede Zeile zu machen, so dass jedes Element kann seinen eigenen Zustand halten. Ich habe etwas ähnliches mit 500+ Zeilen mit einem ListView gemacht und es hat gut funktioniert.

+0

Vielen Dank! Ihr Kopfgeld wird in 6 Stunden vergeben –

2

Mit react-native 0.45.1, machte ich schnell dieses Mock-up mit 1000 Zeilen und der TextInput funktioniert gut. Es blockiert nicht wie in Ihrer Demo .... selbst wenn Sie den ganzen Weg bis zum Ende und wieder zurück scrollen, ist der TextInput Zustand richtig und noch editierbar.

Ich schlage vor, mit diesem Modell zu beginnen, und bauen Sie Ihre Implementierung auf, um zu sehen, wo es bricht.

import React, { Component } from 'react'; 
import { 
    AppRegistry, 
    StyleSheet, 
    Text, 
    View, 
    ListView, 
    TextInput 
} from 'react-native'; 


const mocks = [] 
for (var i = 0; i < 1000; i++) { 
    mocks.push({ 
    id:i, 
    text: `I am row ${i}` 
    }) 
} 


export default class test extends Component { 

    constructor(){ 
    super() 
    this.ds = new ListView.DataSource({ rowHasChanged: (r1,r2) => r1 !== r2 }) 
    this.state = { 
     ds: this.ds.cloneWithRows(mocks), 
    } 
    } 

    renderRow = (value) => { 
    return(
     <View style={ styles.rowContainer }> 
     <Text>{ value.text }</Text> 
     <TextInput 
      style={ styles.textInput } 
      value={ this.state[`comment${value.id}`] } 
      onChangeText={ (text) => this.setState({ [`comment${value.id}`]:text }) } 
     /> 
     </View> 
    ) 
    } 

    render() { 
    return (
     <View style={styles.container}> 
     <ListView 
      dataSource={ this.state.ds } 
      renderRow={ this.renderRow } 
     /> 
     </View> 
    ); 
    } 
} 

const styles = StyleSheet.create({ 
    container: { 
    flex: 1, 
    backgroundColor: '#F5FCFF', 
    }, 
    rowContainer:{ 
    padding:10, 
    marginBottom:10, 
    backgroundColor: 'rgb(222,222,222)' 
    }, 
    textInput:{ 
    backgroundColor: 'white', 
    height: 50, 
    } 
}); 

AppRegistry.registerComponent('test',() => test); 
Verwandte Themen