How to call fetch() inside renderItem on FlatList?

旧街凉风 提交于 2021-01-05 06:40:05

问题


I have been unable to solve this so far, I hope someone from here can help me :)

The situation is as following:

  1. I load a list of users from a department using an API which returns it as JSON (this works).

  2. For each user in the JSON file, I have to fetch another JSON file containing sensor data (this does not work).

I am in fact capable of getting the JSON data from the getStatus() function, but it is not correct. Because, when the FlatList is rendered, the data still has not been fetched, but on refresh, calling fetchUsers(), the sensor data shows up, but it shows the same sensor data on all users and not their own specific sensor data.

At the moment I have made it spit out what ever JSON it receives in a Text element in order to see what was returned...

I am not allowed to upload pictures here, but I have made an album on Imgur which contains images of the application to help explain the issue: https://imgur.com/a/5XLpR

export default class SensorData extends Component {
constructor(props) {
    super(props);
    this.stats = null;
    this.state = { 
        isLoading: true,
        error: false,
        userDataSource: [],
        refreshing: false,
        time: 30,
        navigation: props.navigation,
    };
}

componentDidMount() {
    this.fetchUsers();
}

fetchUsers(){
    return fetch('http://url-to-the-json/json/patients.json')
        .then((response) => response.json())
        .then((response) => {
            this.setState({
                isLoading: false,
                error: false,
                userDataSource: response,
                refreshing: false,
                time: 30,
            }, function () {

            });
        })
        .catch((error) => {
            this.setState({
                isLoading: false,
                error: true
            })
        });
}

getStatus(patientId) {
    fetch("http://url-to-the-json/json/status/" + patientId + ".json")
        .then((response) => response.json())
        .then((responseJson) => {
            this.stats = responseJson;
        })
        .catch((error) => {
            Alert.alert("Error");
        });
    return this.stats;
};

renderItem(item, index) {
    var x = index % 2 === 0;
    status = this.getStatus(item.patientId);
    return (
        <View style={x ? styles.rowEven : styles.rowOdd}>
            <TouchableOpacity style={styles.rowName} onPress={this.handlePress.bind(this, item)}>
                <Text style={styles.rowNameText}>{item.firstname} {item.lastname}</Text>
            </TouchableOpacity>
            <Text>{JSON.stringify(status)}</Text>
        </View>          
    )
}

render() {
    return (
        <View>
            <View style={styles.reloadTimer}>
                <Text style={styles.timerText}>Reloading in {this.state.time} seconds.</Text>
            </View>
            <View style={styles.listView}>
            <FlatList
                    data={this.state.userDataSource}
                    renderItem={({ item, index }) => this.renderItem(item, index)}
                    keyExtractor={item => item.patientId}
                    refreshing={this.state.refreshing}
                    onRefresh={this.handleRefresh}
                    ItemSeparatorComponent={this.renderSeparator}
            />
            </View>
        </View>
    );
}
}

The variable status is the one in question.

I hope I formulated the question in an understandable manner.

The users JSON file looks like this:

  {
    "patientId": "ec276ca9-f9ab-429b-b34e-23fcf448d714",
    "firstname": "Julie",
    "lastname": "Nielsen",
    "birthDate": "1930-01-01T00:00:00Z",
    "departmentId": "709f59ae-67fe-447c-bed3-7b5912703861",
    "patientNumber": null,
    "entryDate": null,
    "dischargeDate": null,
    "editedOn": null,
    "editedBy": null
  }

The sensor data JSON file looks like this:

{
"status": {
      "in_bed": false,
      "in_room": true,
      "clean_diaper": true
    }
}

回答1:


You need to store the result of getStatus in component state like you do with the patients JSON. Assuming you have a "stats" object in your state that maps a patient to their stats, you can do:

getStatus(patientId) {
    fetch("http://url-to-the-json/json/status/" + patientId + ".json")
        .then((response) => response.json())
        .then((responseJson) => {
            let stats = Object.assign({}, this.state.stats);
            stats[patientId] = responseJson;
            this.setState({ stats: stats });
        })
        .catch((error) => {
            Alert.alert("Error");
        });
};

Then, in the renderItem function, you can render the stats from state, or render a placeholder text if the stats haven't been loaded yet. Also, you should not make network requests inside a render function, since they can be called quite often and multiple times for the same component. Instead, you should look into the FlatList API and the callbacks for changes in visibility.

Hope this helps...



来源:https://stackoverflow.com/questions/46834706/how-to-call-fetch-inside-renderitem-on-flatlist

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!