2017-06-21 180 views
9

我想为我的列表视图的每一行中包含的每个textinput设置一个状态值。反应本机ListView TextInput锁定从性能优化呈现

问题是,React Native的ListView组件有一些优化技术,例如删除超出屏幕界限的行。这导致了一个问题,因为TextInputs正在锁定它们的value属性,编辑它们将不再反映更改并且状态值锁定或者什么。我附加了一段视频来展示此行为。

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

尝试使用FlatList,如果您使用的是最近版本的react-native。 http://facebook.github.io/react-native/blog/2017/03/13/better-list-views.html“不再有ListView或DataSources,陈旧的行” –

回答

5

我建议创建一个组件,从而使得各行,以便每个项目可以保持自己的状态。我用一个ListView做了500多行类似的事情,它运行良好。

+0

非常感谢!你的赏金将在6小时内给出 –

2

与反应原生0.45.1,我很快做了1000个行的模拟和TextInput工作正常。它不会像您的演示中一样锁定....即使您一直滚动到结尾并备份,TextInput状态是正确的,仍然是可编辑的。

我建议从这个模型开始,并建立您的实现,以查看它的破坏位置。

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);