Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React Native ListView TextInput locks up from performance optimization rendering

I am trying to set a state value for each textinput contained in each row of my listview.

The issue is that, React Native's ListView Component has a bunch of optimization techniques such as removing rows that are out of screen bounds. This is causing an issue because the TextInputs are locking up their value property, editing them will no longer reflect changes and the state value locks up or something. I've attached a video to show this behavior.

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>
    )
}
like image 775
Thomas Charlesworth Avatar asked Jun 21 '17 03:06

Thomas Charlesworth


1 Answers

I'd recommend creating a component to render each row so each item can hold its own state. I've done something similar with 500+ rows with a ListView and it worked well.

like image 58
Funk Soul Ninja Avatar answered Oct 29 '22 13:10

Funk Soul Ninja