排序数据后强制FlatList重新呈现

时间:2019-12-08 16:30:04

标签: react-native react-native-flatlist

我有一个求职应用。在显示作业的我的JobsComponent中,我添加了一个排序选项,该选项使用户可以按不同条件对作业列表进行排序。流程是这样的:1)我从服务器获取作业-> 2)用户对作业进行排序-> 3)已排序的作业列表重新显示在屏幕上。

问题在于步骤3)无法正常工作。实际的作业列表 正在排序(我可以在日志中看到),但是我的FlatList并未重新呈现。

我尝试过的事情

  1. 我在状态中设置了一个标志sortOrderChanged。每当用户选择排序选项时,我都会在componentDidMount()方法中更改此标志:
this.setState({
                sortOrderChanged: !this.state.sortOrderChanged,
                selectedSortOrder: dataFromChild
            });

并将其作为extraData传递给FlatList:

<FlatList 
                    data={sort_array}
                    extraData={props.sortOrderChanged}
                    renderItem={renderJobItem}
                    keyExtractor={(item, index) => index.toString()}
                    style={{marginTop: 10}}
                    />

但这没有帮助。我还尝试将整个状态发送到FlatList并将其传递给extraData,但是它也没有用。我认为问题是我的数据实际上并未更改,而是已排序。但是,我不知道如何强制它重新渲染。有人可以帮我吗?

下面是我的JobsComponent.js:

function RenderJobs(props) {
    var json = JSON.parse(props.jobsData);
    var sort_array = [];
    for (var _id in json) {
        sort_array.push({
            _id:_id,
            jobtitle: json[_id].jobtitle,
            company: json[_id].company,
            duration_driving_value:json[_id].duration_driving.value,
            duration_transit_value: json[_id].duration_transit.value,
            duration_walking_value: json[_id].duration_walking.value,
            duration_driving:json[_id].duration_driving.text,
            duration_transit:json[_id].duration_transit.text,
            duration_walking:json[_id].duration_walking.text,
            date: json[_id].date,
            formatedDescription: json[_id].formatedDescription,
            applyUrl: json[_id].applyUrl
        });
    }
    //sort the list based on user selection
    if (props.sortOrder === props.sortArray[0]) {
        sort_array.sort(function(x,y){return new Date(y.date) - new Date(x.date)});
    }
    else if (props.sortOrder === props.sortArray[1]) {
        sort_array.sort(function(x,y){return x.duration_driving_value - y.duration_driving_value});
    }
    else if (props.sortOrder === props.sortArray[2]) {
        sort_array.sort(function(x,y){return x.duration_transit_value - y.duration_transit_value});
    }
    else {
        sort_array.sort(function(x,y){return x.duration_walking_value - y.duration_walking_value});
    }


    const renderJobItem = ({item}) => {
        var  durationCarApi, durationPublicTransportApi, durationWalkApi, formattedApiDate, formattedJobDescription;
        //format data
        return (
            <Panel //custom component used to display each job
                jobTitle={item.jobtitle}
                company={item.company}
                durationCar={durationCarApi}
                durationTram={durationPublicTransportApi}
                durationWalking={durationWalkApi}
                dateAdded={formattedApiDate}
                onPress={() => 
                    {
                    props.navigation.navigate('JobDetails', {
                        jobTitle: item.jobtitle,
                        company: item.company,
                        durationCar: durationCarApi,
                        durationTram: durationPublicTransportApi,
                        durationWalking: durationWalkApi,
                        jobDescription: formattedJobDescription,
                        applyUrl: item.applyUrl
                })
                    }
                }/>
        );
    }

    //handle loading/error scenarios
        return (
            <FlatList 
                    data={sort_array}
                    extraData={props.sortOrderChanged}
                    renderItem={renderJobItem}
                    keyExtractor={(item, index) => index.toString()}
                    style={{marginTop: 10}}
                    />
        );

}

class Jobs extends Component {

    constructor(props) {
        super(props);
        this.state = { 
            jobTitle: this.props.navigation.getParam('jobTitle', ''),
            address: this.props.navigation.getParam('address', 'error'),
            sortOrderChanged: false,
            sortArray: [0,1,2,3],
            selectedSortOrder: 1 //default is sort_driving
         };
      }

    componentDidMount() {

        handleSorting = (dataFromChild) => {
            console.log('Sort order clicked: ' + dataFromChild);
            this.RBSheet.close();
            this.setState({
                sortOrderChanged: !this.state.sortOrderChanged,
                selectedSortOrder: dataFromChild
            });
    }

    render() {
        return(
            <ScrollView contentContainerStyle={styles.bkg}>
                <RenderJobs 
                    jobsData={JSON.stringify(this.props.jobs.jobs)}
                    isLoading={this.props.jobs.isLoading}
                    errMess={this.props.jobs.errMess}
                    navigation={this.props.navigation}
                    sortOrder={this.state.selectedSortOrder}
                    sortArray={this.state.sortArray}
                    sortOrderChanged={this.state.sortOrderChanged} 
                    />
                <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
                    <RBSheet //custom component used to render the sorting options
                        ref={ref => {this.RBSheet = ref;}}
                        height={200}
                        duration={250}
                        customStyles={{
                            container: {
                            justifyContent: "center",
                            alignItems: "center"
                        }
                    }}>
                    <SortSheet //this is the child component used to render the sorting options
                        sortOrder={this.handleSorting}
                        sortArray={this.state.sortArray}/>
                    </RBSheet>
                </View>
            </ScrollView>
        )
    }
}

2 个答案:

答案 0 :(得分:0)

将数据从本地变量移动到状态。 或在else之后添加 forceUpdate

答案 1 :(得分:0)

解决方案是将keyExtractor更改为item._id:

<FlatList 
                    data={props.jobsData}
                    extraData={props.sortOrderProps}
                    renderItem={renderJobItem}
                    keyExtractor={(item, index) => item._id}
                    style={{marginTop: 10}}
                    />