Salut!
Am o problemă cu un FlatList pe care vreau să-l forțez să se randeze după ce sortez un obiect, dar nu reușesc să fac asta. Atașez mai jos detalii despre problemă - sunt în engleză, deoarece am postat și pe alte site-uri internaționale.
I have a jobs app. In my JobsComponent, where I display the jobs, I have added a sort option that allows users to sort the list of jobs by different criteria. The flow is this: 1) I get the jobs from the server -> 2) the user sorts the jobs -> 3) the sorted list of jobs is re-rendered on the screen.
The problem is that step 3) is not working. The actual list of jobs is being sorted (I can see that in the logs), but my FlatList is not being re-rendered.
Below is my 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>
)
}
}
What I have tried
- I have a flag, sortOrderChanged, set in my state. Whenever the user selects a sorting option, I change this flag in my componentDidMount() method whenever the sort order changes:
this.setState({
sortOrderChanged: !this.state.sortOrderChanged,
selectedSortOrder: dataFromChild
});
and pass it to FlatList as extraData:
<FlatList
data={sort_array}
extraData={props.sortOrderChanged}
renderItem={renderJobItem}
keyExtractor={(item, index) => index.toString()}
style={{marginTop: 10}}
/>
- I moved my jobs data to the local state as follows:
In my JobsComponent, I changed my state to contain the jobs data
this.state = { jobs: JSON.stringify(this.props.jobs.jobs), }
I passed the state to the component that includes the FlatList
<RenderJobs sortOrderProps={this.state} />
and passed sortOrderProps to extraData.
<FlatList extraData={props.sortOrderProps}/>
Din păcate, niciuna dintre soluțiile de mai sus nu funcționează. Aveți vreo idee de ce?
Mulțumesc!