等待异步数据在React或React Native中以状态存储的正确方法

时间:2017-07-27 01:18:43

标签: javascript reactjs react-native

我需要从我的SQLite数据库中获取数据,然后将其保存在我的组件状态中。数据库部分工作正常,问题是它没有足够快地保存到状态。如果我用setTimeout添加一些人工延迟,那么它工作正常。我怎样才能更好地将这些东西捆绑在一起,这样才能在没有百万次回调的情况下以正确的顺序和时间运行?

这不起作用:

let returnedData;
// This function works, the data comes back correctly eventually
returnedData = getDataFromDB();
this.setState({
    dbData: returnedData //but returnedData is still empty at this point
  })
// Data is not back in time to see in the variable or in state:
console.log(returnedData); // Undefined
console.log(this.state.dbData); // Undefined

但这确实有效:

let returnedData;
returnedData = getDataFromDB();

// If I add this tiny delay, it all works
setTimeout(function(){
     this.setState({
         dbData: returnedData
     })
     console.log(returnedData); // Shows correct data
     console.log(this.state.dbData); // Shows correct data
},100);

我想尝试找到一种方法,让它在没有人工延迟的情况下工作。当我的组件正在加载时,我将需要在componentWillMount中执行大约3个这样的数据库查询,并且在呈现组件之前需要知道我有数据。

谢谢!

1 个答案:

答案 0 :(得分:1)

使用componentDidMount生命周期钩子在初始化组件时获取异步数据。这应该在使用异步获取的数据的组件中完成,或者在多个组件使用的数据的最近共同祖先中完成。这样做的原因是在异步检索完成后减少重新渲染的组件的数量。

  

请注意,在您的异步数据可用之前,您还需要考虑 loading 状态。

以下是原则的基本示例。

class ComponentThatRequiresAsyncData extends PureComponent {
    constructor( props ) {
        super( props );

        // initialize state
        this.state = {
            data: null
        }
    }

    // handle async operation in this lifecycle method to ensure
    // component has mounted properly
    componentDidMount() {
        axios.get( "some_url" )
            .then( ( response ) => {
                // once you have your data use setState to udpate state
                this.setState( ( prevState, props ) => {
                    return { data: response.data };
                })
            })
            .catch( ( error ) => {
                // handle errors
            });
    }

    render() {
        const { data } = this.state;
        return (
            {
                data ?
                    <WhatEverIWantToDoWithData data={ data } /> :
                    <p>Loading...</p>
          }
        );
    }
}

对于因事件而需要加载的数据使用相同的想法,例如单击按钮。您可以使用componentDidMount制作自己的方法,在http调用的setState方法中通过then进行异步调用和更新状态。如果您将它用作事件处理程序,请确保在构造函数中绑定方法的this上下文。

希望这会有所帮助。如果您有任何疑问,请询问!