如何在componentDidMount函数中调用异步函数?

时间:2019-06-25 20:57:49

标签: javascript react-native react-native-android

我正在尝试从API中获取一些数据并将其放入flatList中。 flatList中的每一行都有一个白色星形按钮,按下该按钮会将此项添加到保存在AsyncStorage中的收藏夹中。我要做的是获取保存在本地的密钥,并检查此项目是否在我要显示黑星的收藏夹列表中。我无法在该状态下填充“收藏夹”数组。

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 *
 * @format
 * @flow
*/

import React, { Component } from 'react';
import {
    StyleSheet, Text, View, ActivityIndicator, AsyncStorage,
    Image, ToastAndroid, TouchableOpacity, FlatList
} from 'react-native';

export default class App extends Component {

    constructor(props) {
        super(props)
        this.state = {
            isLoadingData: true,
            dataSourceEmpty: null,
            favorites: null
        }
    }

    componentDidMount() {
        return fetch('http://barcelonaapi.marcpous.com/bicing/stations.json')
            .then((response) => response.json())
            .then((JsonResponse) => {

                this.setState({
                    isLoadingData: false,
                    dataSourceEmpty: JsonResponse.data.bici,
                    favorites: null
                })
            })
            .catch((error) => {
                console.log(error);
            });
    }

    _touchListener = (item) => {
        alert("ID is:" + item.id + "\n"
            + "Latitude is: " + item.lat + "\n"
            + "Longitude is:" + item.lon)
    };

    makeFavorite(item) {
        this.saveData(item);
        ToastAndroid.show(
            'This station has been added to favorites!',
            ToastAndroid.SHORT
        );
    }

    saveData(station) {
        AsyncStorage.setItem(station.id + "", station.name);
    }

    DATABASE_getAllBusStations = () => {
        return new Promise(async (resolve, reject) => {
            try {
                let keys = await AsyncStorage.getAllKeys();
                resolve(keys)
            } catch (error) {
                reject(new Error('Error getting keys from AsyncStorage: ' +
                    error.message))
            }
        });
    }

    checkifInDatabase = async () => {
        try {
            var keys = await this.DATABASE_getAllBusStations();
            this.setState({
                isLoadingData: true,
                dataSourceEmpty: null,
                favorites: keys
            })
        } catch (error) {
            console.log(error);
        }
    }

    render() {
        if (this.state.isLoadingData) {
            return (
                <View style={styles.container}>
                    <ActivityIndicator size="large" animating />
                </View>
            );
        }
        else {
            return (
                <View style={styles.container}>
                    <Text style={styles.header}>
                        BARCELONA BUS STATIONS
              </Text>
                    <FlatList
                        data={this.state.dataSourceEmpty}
                        renderItem={({ item }) => {
                            let source = './Assets/fav.png';
                            // if(this.state.favorites.includes(item.id))
                            // {
                            //   source = './Assets/favblack.png';
                            // }
                            return <TouchableOpacity style={styles.item}
                                onPress={() => this._touchListener(item)}>
                                <View style={styles.row}>
                                    <Text style={styles.textStyle}>
                                        {item.name}
                                    </Text>
                                    <View style={styles.buttonStyle}>
                                        <TouchableOpacity onPress=
                                            {() => this.makeFavorite(item)}>
                                            <Image
                                                source={require(source)}
                                                style={styles.imageStyle}
                                            />
                                        </TouchableOpacity>
                                    </View>
                                </View>
                            </TouchableOpacity>
                        }
                        }
                        keyExtractor={(item, index) => index.toString()}
                    />
                </View>
            );
        }
    }
}
const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: '#F5FCFF',
    },
    indicator: {
        alignItems: 'center',
        justifyContent: 'center',
    },
    row:
    {
        flexDirection: 'row',
        justifyContent: 'space-between'
    },
    item: {
        padding: 10,
        borderBottomWidth: 1,
        borderBottomColor: '#eee',
        backgroundColor: 'skyblue'
    },
    header:
    {
        backgroundColor: '#F03209',
        textAlign: 'center',
        padding: 10,
        color: 'skyblue',
        fontSize: 20
    },
    imageStyle:
    {
        width: 50,
        height: 50
    },
    textStyle:
    {
        padding: 10
    }
});

2 个答案:

答案 0 :(得分:0)

您可以嵌套调用,也可以将其移到异步功能。参见下面的示例。

import * as React from 'react';
import { RouteComponentProps } from 'react-router-dom';

interface ITestComponentState {
    message_1: string;
    message_2: string;
    message_3: string;
    message_4: string;
}

export default class TestComponent extends React.Component<RouteComponentProps<{}>, ITestComponentState> {
    renders = 0;
    constructor(props: any) {
        super(props);
        this.state = {
            message_1: null,
            message_2: null,
            message_3: null,
            message_4: null
        }
    }

    componentDidMount() {
        /**Using nested fetch calls**/
        fetch('api/Local/GetData')
            .then(response => response.text())
            .then(message_1 => {
                fetch('api/Local/GetData')
                    .then(response => response.text())
                    .then(message_2 => {
                        this.setState({ message_1, message_2 });
                    });
            });

        /**Using an async function**/
        this.getMessages().then((messages: string[]) => this.setState({ message_3: messages[0], message_4: messages[1] }));
    }

    async getMessages() {
        let message_3 = await fetch('api/Local/GetData').then(response => response.text());
        let message_4 = await fetch('api/Local/GetData').then(response => response.text());
        return [message_3, message_4];
    }

    public render() {
        const { message_1, message_2, message_3, message_4 } = this.state;
        this.renders++;
        return (
            <div>
                <h1 className="test">Message 1: {message_1}</h1>
                <h1 className="test">Message 2: {message_2}</h1>
                <h1 className="test">Message 3: {message_3}</h1>
                <h1 className="test">Message 4: {message_4}</h1>
                <h2 className="test">Renders: {this.renders}</h2>
            </div>
        );
    }
}

这是在第一个抓取中嵌套一个抓取。

        fetch('api/Local/GetData')
            .then(response => response.text())
            .then(message_1 => {
                fetch('api/Local/GetData')
                    .then(response => response.text())
                    .then(message_2 => {
                        this.setState({ message_1, message_2 });
                    });
            });

这将它们放在异步方法中,并在componentDidMount内部调用该方法。

this.getMessages().then((messages: string[]) => this.setState({ message_3: messages[0], message_4: messages[1] }));
async getMessages() {
        let message_3 = await fetch('api/Local/GetData').then(response => response.text());
        let message_4 = await fetch('api/Local/GetData').then(response => response.text());
        return [message_3, message_4];
    }

结果是:

Message 1: "Hello World!"
Message 2: "Hello World!"
Message 3: "Hello World!"
Message 4: "Hello World!"
Renders: 3

答案 1 :(得分:0)

如何使componentDidMount本身异步?

async componentDidMount() {
   try{
      const response = await axios.get('http://barcelonaapi.marcpous.com/bicing/stations.json')
      if(response.data.success){
         this.setState({
            isLoadingData: false,
            dataSourceEmpty: response.data.bici,
            favorites: null
      })
   }catch(error){
      console.log(error);
   }
}