簡體   English   中英

react-native排序console.log中的Render和Constructor

[英]Render and Constructor in react-native ordering console.log

我在理解此React本機應用程序中的程序流程時遇到了一些困難。

我已經在整個應用程序中放入了console.log語句,以嘗試理解。

因此,我將構造函數中的狀態初始化為lat:0,long:0,err:null和markers:[]。 然后在構造函數中,我調用API方法以獲取所有位置並填充markers方法。 印刷品的輸出如下:

//從render方法

 [] [] [] 

//然后返回構造函數async方法,並設置標記

 {markers: [{title: "A", coordinate: {latitude: 0, longitude: 1}, description: "abc"}, {title: "B", coordinate: {latitude: 0, longitude: 1}, description: "abc"}]} 

然后我調用render方法,我知道這可能是很糟糕的做法,但這只是嘗試調試,希望標記在地圖上可見。

但是,此后,render方法繼續打印[],這對我來說似乎真的很奇怪,因為我只是在構造函數中進行了設置!

任何幫助,將不勝感激。

 import React, { Component } from 'react'; import { Platform, StyleSheet, Text, View } from 'react-native'; import MapView from 'react-native-maps'; const styles = StyleSheet.create({ container: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'flex-end', alignItems: 'center', }, map: { position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, }, }); const instructions = Platform.select({ ios: 'Press Cmd+R to reload,\\n' + 'Cmd+D or shake for dev menu', android: 'Double tap R on your keyboard to reload,\\n' + 'Shake or press menu button for dev menu', }); class App extends Component { constructor(props) { super(props); this.state = { latitude: 0, longitude: 0, error: null, markers: [] }; navigator.geolocation.getCurrentPosition( (position) => { this.state = { latitude: position.coords.latitude, longitude: position.coords.longitude, error: null, }; }, (error) => this.setState({ error: error.message }), { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 }, ); fetch(API_URL) .then((response) => response.json()) .then((responseJson) => { var relevantLocations = [] for (var i = 0; i < responseJson.length; i++) { var location = responseJson[i]; relevantLocations.push({ title: location.name, coordinate: {latitude: location.latitude, longitude: location.longitude}, description: "test" + i }); } console.log("Setting state"); this.state = { markers: relevantLocations }; console.log(this.state); this.render(); }) .catch((error) => { console.error(error); }); } onRegionChange = (region) => { this.setState({ region }); } onPress = () => { } render() { console.log(this.state.markers); return ( <View style={styles.container}> <MapView style={styles.map} onRegionChange={this.onRegionChange} onPress={this.onPress} > {this.state.markers.map(marker => { return <MapView.Marker key={marker} coordinate={marker.coordinate} title={marker.title} description={marker.description} /> })} </MapView> </View> ); } } export default App; 

我在構造函數中設置的變量如何被覆蓋?

謝謝

通常,React中的異步調用被放置在componentDidMount()生命周期方法中,該方法在首次調用render()之后立即被調用。 constructor用於初始化,即初始化組件state ,對傳入的任何props調用super ,並bind組件方法。 我會將所有異步調用(包括對navigatorfetchAPI的調用) fetchAPIcomponentDidMount並確保您初始化的任何state都不會在render上引起任何錯誤。 正如Tyler McGinnis在這篇文章中寫道:

AJAX請求應該進入componentDidMount生命周期事件中。

這有幾個原因,

Fiber是React調節算法的下一個實現,將能夠根據需要啟動和停止渲染,以提高性能。 其中一項權衡取舍是componentWillMount,這是另一個可能決定發出AJAX請求的生命周期事件,將是“不確定的”。 這意味着React可能會在需要時隨時開始調用componentWillMount。 對於AJAX請求,這顯然是一個不好的公式。

您不能保證在組件安裝之前AJAX請求不會得到解決。 如果確實如此,那意味着您將嘗試在未安裝的組件上設置setState,這不僅不起作用,而且React也會為您大喊大叫。 在componentDidMount中執行AJAX可以確保存在要更新的組件。

這是一個使用componentDidMount的完整示例,並在解決了所有異步請求之后正確設置了state

import React, { Component } from 'react';
import {
  Platform,
  StyleSheet,
  Text,
  View
} from 'react-native';
import MapView from 'react-native-maps';

const styles = StyleSheet.create({
  container: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
  map: {
    position: 'absolute',
    top: 0,
    left: 0,
    right: 0,
    bottom: 0,
  },
});

const instructions = Platform.select({
  ios: 'Press Cmd+R to reload,\n' +
    'Cmd+D or shake for dev menu',
  android: 'Double tap R on your keyboard to reload,\n' +
    'Shake or press menu button for dev menu',
});

class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      latitude: 0,
      longitude: 0,
      error: null,
      markers: []
    };
  }

  componentDidMount() {

     navigator.geolocation.getCurrentPosition(
      (position) => {

        fetch(API_URL)
           .then((response) => response.json())
           .then((responseJson) => {
              var relevantLocations = []
              for (var i = 0; i < responseJson.length; i++) {
                var location = responseJson[i];
                relevantLocations.push({
                  title: location.name,
                  coordinate: {latitude: location.latitude, longitude: 
                    location.longitude},
                  description: "test" + i
                });
              }
             console.log("Setting state");
             this.setState({
                ...this.state
                latitude: position.coords.latitude,
                longitude: position.coords.longitude,
                markers: relevantLocations
             });
           })
           .catch((error) => {
             console.error(error);
           });

       },
      (error) => this.setState({ ...this.state, error: error.message }),
        { enableHighAccuracy: true, timeout: 20000, maximumAge: 1000 },
      );


  }

  onRegionChange = (region) => {
    this.setState({ region });
  }

  onPress = () => {
  }

  render() {
    console.log(this.state.markers);
    return (
      <View style={styles.container}>
        <MapView style={styles.map}
          onRegionChange={this.onRegionChange}
          onPress={this.onPress}
        >
        {this.state.markers.map(marker => {
            return <MapView.Marker
              key={marker}
              coordinate={marker.coordinate}
              title={marker.title}
              description={marker.description}
            />
          })}
        </MapView>
      </View>
    );
  }
}

export default App;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM