rgovindji / react-native-atoz-list

React Native Listview which handles large data sets and can scroll to sections using an alphabetical scroll list
185 stars 101 forks source link

the component do not re-render when a state is updated #29

Open komodor8 opened 6 years ago

rgovindji commented 6 years ago

Please submit a pull request

komodor8 commented 6 years ago

@rgovindji
I cannot make a PR because I am not sure what to change.

I just know in file FixedHeightWindowedListView.js:233 shouldUpdate={data !== this.__rowCache[key]} return false and doesn't update the row.

_--- I run the app on iOS Simulator. _"react": "^16.3.2", "react-native": "^0.55.4", "react-native-atoz-list": "^1.0.3", "react-native-meteor": "^1.2.0",__

adurandet commented 6 years ago

I have the same problem.

If the list keeps the same items but a value of one of the item is different, the list do not re-render...

komodor8 commented 5 years ago

@rgovindji Does anyone have a solution ?

rgovindji commented 5 years ago

I haven't been maintaining this package in awhile. I never tested it with items that update, I usually would just load data once and render once.

1111mp commented 5 years ago

chooseHandle = (id) => { let newPeople = this.state.peoples; let index = newPeople.indexOf(id); if(index > -1){ newPeople.splice(index, 1); }else{ newPeople.push(id) } this.setState(()=>{ return { peoples: newPeople } }) }

getChecked = (id) => { let flag = false; this.state.peoples.forEach((item,index)=>{ if(item == id){ flag = true } }) return flag }

_renderCell = (data) => { return ( <TouchableHighlight underlayColor='#D9D9D9' onPress={()=>{this.chooseHandle(data.id)}}>

this.chooseHandle(data.id)} /> {data.text} {data.id} - {data.deptName}
  </TouchableHighlight>
)

}

_renderSection = (data) => { return ( <View style={{ height: scaleSize(50), justifyContent: 'center', backgroundColor: '#eee', paddingLeft: scaleSize(20) }}> <Text style={{color:'#181818'}}>{data.sectionId} ) }

render() { const { addrBook } = this.props.rootStore.addrBookStore; let length = this.state.peoples.length; return (

this.props.navigation.goBack()} > 取消 选择联系人 { length == 0 ? ( 完成 ) : ( 完成({length}) ) }
)

} } Have you considered this situation:That is to complete the function of selecting contacts. But after I checked, the view did not render again. / shouldComponentUpdate(newProps) { return newProps.shouldUpdate; } / When I annotated the code, it turned out to be very poor. How should I complete this demand? Please give your advice. Thanks

1111mp commented 5 years ago

@rgovindji Please give your advice. Thanks

1111mp commented 5 years ago

@komodor8 @rgovindji Hello, I think I found a solution.My English is not very good. I can only translate it through translator. Well, I solved the problem I mentioned above.It's a little complicated.My idea is that I control whether each item's shouldComponentUpdate returns true or false according to my actions. image image image It's hard to make it clear. I don't know if you can understand it. inked815595453589734625_li Now I can choose and cancel smoothly. So I think the problem of how to update views has been solved. I hope this can give you some help. Of course, if I can't understand what I mean, I can send you my complete code. Thank you.

komodor8 commented 5 years ago

@1111mp This didn't work for me. I changed FixedHeightWindowedListView.js file

__renderCells(rows, firstRow, lastRow) {
    for (var idx = firstRow; idx <= lastRow; idx++) {
      let data = this.props.dataSource.getRowData(idx);
      let id = idx.toString();
      let parentSectionId = '';

      // TODO: generalize this!
      if (data && data.get && data.get('guid_token')) {
        id = data.get('guid_token');
      }

      let key = id;

      if (!(data && _.isObject(data) && data.sectionId)) {
        parentSectionId = this.props.dataSource.getSectionId(idx)
        key = `${key}-${id}`;
      }

      let shouldUpdate = false;
      if ( this.__rowCache[key] && this.__rowCache[key].id && !this.props.handleStatus) {
          let flag = this.props.items.indexOf(this.__rowCache[key].id);
          shouldUpdate = flag == - 1 ? false : true;
          this.items = _.cloneDeep(this.props.items)
      }
      if ( this.__rowCache[key] && this.__rowCache[key].id && this.props.handleStatus) {
          let flag = this.items.indexOf(this.__rowCache[key].id);
          shouldUpdate = flag == - 1 ? false : true;
      }

      rows.push(
        <CellRenderer
          key={key}
          shouldUpdate={shouldUpdate}
          render={this.__renderRow.bind(this, data, parentSectionId, idx, key)}
        />
      );

      this.__rowCache[key] = data;
    }
  }

and my component

addRemoveFonction(fonction) {
        var fonc = this.state.selectedFonctions;
        if (fonc.includes(fonction._id)){
            var index = fonc.indexOf(fonction._id);
            if (index > -1) {
                fonc.splice(index, 1);
                this.setState({ handleStatus: true });
            }
        } else {
            fonc.push(fonction._id);
            this.setState({ handleStatus: false });
        }
        this.setState({
            selectedFonctions: fonc,
        }, function() {
            this.setHeaderButton();
        });
    }
_renderCell(fonction) {
        console.log('handle _renderCell');
        if (this.state.selectedFonctions.includes(fonction._id)) {
            console.log('checked');
            return (<TouchableOpacity
                    style={styles.cell}
                    onPress={() => this.addRemoveFonction(fonction)} >
                    <Text style={{ fontSize: 15 }}>{fonction.name}</Text>
                        <View>
                            <Icon name="check-square-o" color="gray" size={20} style={styles.rightIcon}/>
                            <Text>true</Text>
                        </View>
                </TouchableOpacity>);
        } else {
            console.log('not checked');
            return (<TouchableOpacity
                style={styles.cell}
                onPress={() => this.addRemoveFonction(fonction)} >
                <Text style={{ fontSize: 15 }}>{fonction.name}</Text>
                    <View>
                        <Icon name="square-o" color="gray" size={20} style={styles.rightIcon}/>
                        <Text>false</Text>
                    </View>
            </TouchableOpacity>);
        }
    }
<AlphabetListView
                    data={this.state.fonctions}
                    renderCell={this._renderCell}
                    cellHeight={80}
                    renderSection={this._renderHeader}
                    sectionHeaderHeight={37}
                    sectionListStyle={{backgroundColor:'white'}}
                    items={this.state.fonctions}
                    handleStatus={this.state.handleStatus}
                />
1111mp commented 5 years ago

@komodor8 Do you have items and handleStatus in your component passed in AtoZList.js? like this: image Let me take my project as an example to explain: First, I need to click on each item to select or cancel and update the view.So I passed two props here. image peoples:I will add or delete the current item data in this array after each selection or cancellation. handleStatus:Let me know if I am currently in the process of selecting or cancelling selection. Then I got these two props in the FixedHeightWindowedListView.js file. image image image In the selection operation, the peoples props at this time has push the item I clicked.So at this point I just need to find the item from the peoples and turn on its shouldComponentUpdate state.At this point, all the other items'shouldComponentUpdate state is closed, and only my current item is turned on, so app only needs to update the state of this item, so the performance of app is greatly improved.

Of course, in the deselect operation, I just need to find the item I want to deselect from the selected state Peoples and update the view.At this point, I need a variable to save the state data of peoples before I cancel the operation.So in FixedHeightWindowedListView.js file, I use this.peoples variable to save. image Then I can open the shouldComponentUpdate state of these selected item.The result is that app can respond normally to what I have done.

1111mp commented 5 years ago

@komodor8 I have improved my method and I hope it will work for you. AtoZList: image renderCell:

1111mp commented 5 years ago

@komodor8 I improved my method. It's much simpler.It did what I needed. image renderCell: image image This this.state.item is used to save the tiem that is currently clicked. image image image Then it works.