除非我在setTimeout内包装console.log(this.state),否则无法在.then(json)提取调用之外访问this.state或this.props

时间:2019-01-09 02:39:58

标签: javascript reactjs redux react-redux fetch

我无法访问this.state之外的this.props.then(json)。如果我尝试做console.log(this.state, this.props), 我在日志中看到状态和道具,但是一旦我单击它,两个数组都是空的。但是,如果我将console.log包裹在setTimeout()周围,则可以使用。但是,这给我带来了范围界定问题,因为我需要像道具一样将这个组件的状态作为道具注入到FeedTable组件中---

<FeedTable fetch_call={this.state.quakes_list} />

有问题的console.logconsole.log('QUAKES LIST COMPONENT STATE ', this.state.quakes_list);

一旦我将其移动到以下})下面,它将呈现一个空白的[]

任何帮助将不胜感激!这是该组件的完整代码:

class QuakeFeed extends Component {

    constructor (props) {
        super(props);

        this.state = {
            current_quakes: [],
            quakes_list: []
        }
    }

    componentDidMount() {

        // USE CURRENT TIME TO FETCH LIVE DATA
        // GET DATE AND TIME TODAY
        let time_now = new Date().getTime();
        let date_now = new Date(time_now);
        let data_now = date_now.toString();     

        // SPLIT THE DATE TO EXTRACT TO 'YEAR-MONTH-DAY' FORMAT
        let split_date = data_now.split(' ');

        // SEGREGATE MONTH AND RETURN NUMBER INSTEAD OF MONTH       
        let date_arr = split_date.slice(1,4);

        // SHUFFLE ARRAY TO PROPER FORMAT           
        let year  = date_arr[2];
        let month = date_arr[0];
        let day   = date_arr[1];

        // IF MONTH STRING, PARSE TO NUMERIC
          month === 'Dec' ? month = '12' 
        : month === 'Nov' ? month = '11' 
        : month === 'Oct' ? month = '10' 
        : month === 'Sep' ? month = '09' 
        : month === 'Aug' ? month = '08' 
        : month === 'Jul' ? month = '07'
        : month === 'Jun' ? month = '06' 
        : month === 'May' ? month = '05' 
        : month === 'Apr' ? month = '04' 
        : month === 'Mar' ? month = '03' 
        : month === 'Feb' ? month = '02' 
        : month === 'Jan' ? month = '01' 
        : null;

        // TODAY USING MODIFIED YEAR, MONTH, DATE
        const today = [year, month, day]
        let yesterday = day - 1;        
        yesterday.toString();

        // FETCH CALL TO GET DATA (ARROW FUNCTION TO BIND TO PARENT SCOPE)
        const repeat_fetch = () => {

            // ----------------- INITIAL FETCH -----------------
                // USE THE VARIABLES TO PLUG IN YEAR, MONTH, DAY AND INITIATE FETCH CALL
                fetch ('https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=' + year + '-' + month + '-' + yesterday + 
                       '&endtime=' + year + '-' + month + '-' + day + '&minmagnitude=5')

                .then((response) => {
                    return response.json();
                })

                .then((json) => {       

                    let eq_props = json.features;

                    store.dispatch({ type: 'FETCH-RESPONSE', payload: eq_props })

                    // EARTHQUAKE DATA FROM FETCH 
                    let fetched_req = store.getState();

                    // SET COMPONENT STATE TO STATE FROM REDUX STORE
                    this.setState({current_quakes: fetched_req});                   

                    // LOG CURRENT EARTHQUAKES
                    // console.log('Data', this.state.current_quakes);

                    // CURRENT EARTHQUAKES
                    const quakes = [].slice.call(this.state.current_quakes.quake_data);

                    // STORE QUAKES IN OBJECT TO PACKAGE AND PUSH INTO REDUX STORE
                    let quake_table_data = {};                  

                    for (var i = 0; i < quakes[0].length; i++) {

                        // LOCATION, MAGNITUDE, TIME OF CURRENT EARTHQUAKES
                        const quake_location = quakes[0][i].properties.place;
                        const quake_mag      = quakes[0][i].properties.mag;
                        const quake_time     = new Date(quakes[0][i].properties.time).toLocaleString();

                        quake_table_data.loc = quake_location;
                        quake_table_data.mg  = quake_mag;
                        quake_table_data.tim = quake_time;                      

                        /* 
                            PUSHES THIS OBJECT TO THE REDUX STORE SO THAT YOU CAN ACCESS IT INSIDE 
                            THE FEED TABLE COMPONENT AND CREATE A DYNAMIC TABLE 
                        */
                        store.dispatch({ type: 'STORE-QUAKES', payload: quake_table_data });
                    } // END LOOP                   

                    // GET PROPS FROM mapStateToProps OF REDUX STATE AND SET STATE                  
                    this.setState({ quakes_list: this.props.e_quakes[0]});
                    console.log('QUAKES LIST COMPONENT STATE ', this.state.quakes_list);
                })

            // -------------------------------------------------

            setTimeout(function() {
                // USE THE VARIABLES TO PLUG IN YEAR, MONTH, DAY AND INITIATE FETCH CALL
                fetch ('https://earthquake.usgs.gov/fdsnws/event/1/query?format=geojson&starttime=' + year + '-' + month + '-' + yesterday + 
                       '&endtime=' + year + '-' + month + '-' + day + '&minmagnitude=5')

                .then((response) => {
                    return response.json();
                })

                .then((json) => {                               
                    repeat_fetch();     
                })
            }, 330000);

        } // END repeat_fetch()

        repeat_fetch();
    }
    render() {
        return (
            <div className='section-quake-feed'>

                <FeedTable fetch_call={this.state.quakes_list} />

            </div>
        )
    }
    }

    function mapStateToProps(state) {
        return {
            e_quakes: state.quake_data
        }
    }

    export default connect(mapStateToProps)(QuakeFeed);

1 个答案:

答案 0 :(得分:1)

memset(this, 0, sizeof(A))外部登录quakes_list时,其为空数组的原因是,当您调用.then时,异步调用尚未返回。操作顺序为:

  1. 呼叫console.log(在响应返回之前,fetch中的代码不会开始)
  2. 调用.then(因为这是下一个同步命令),它将记录您在console.log中初始化的空数组
  3. 响应从this.state返回,并且fetch数据处于状态

希望这能回答您的问题...我的猜测是,您在获取quakes_list来呈现<FeedTable>时也遇到了问题,因为调用quakes_list时它没有处于状态。在这种情况下,一种常见的解决方案是检查状态中的属性,如果不存在则返回一个加载器:

render

发生的事情是:render() { return ( <div className='section-quake-feed'> {this.state.quakes_list.length ? ( <FeedTable fetch_call={this.state.quakes_list} /> ) : ( "Loading..." // Or some fallback Loader component, or `null` )} </div> ) } 被设为0,因此调用render并返回回退,然后在设置quakes_list.length时,quakes_list导致重新呈现,并且FeedTable组件已呈现。