反应本机排序中的渲染和构造函数 console.log
Render and Constructor in react-native ordering console.log
我在理解这个 React Native 应用程序中的程序流程时遇到了一些困难。
我已经在整个应用程序中添加了 console.log 语句,以尝试理解。
所以我在构造函数中将状态初始化为lat:0,long:0,err:null和标记:[]。然后在构造函数中,我调用我的 API 方法来获取所有位置并填充标记方法。打印的输出如下:
//来自render方法
[]
[]
[]
//然后构造函数异步方法returns和我们设置标记
{markers: [{title: "A", coordinate: {latitude: 0, longitude: 1}, description: "abc"},
{title: "B", coordinate: {latitude: 0, longitude: 1}, description: "abc"}]}
然后我调用渲染方法,我知道这可能是一种糟糕的做法,但这只是为了尝试调试,希望标记随后在地图上可见。
然而,在此之后,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
ing 组件方法。我会把你所有的异步调用,包括对 navigator
和 fetchAPI
的调用移到 componentDidMount
中,并确保你初始化的任何 state
都不会在 [=22] 上造成任何错误=].正如 Tyler McGinnis 在 this post 中所写:
AJAX requests should go in the componentDidMount lifecycle event.
There are a few reasons for this,
Fiber, the next implementation of React’s reconciliation algorithm, will have the ability to start and stop rendering as needed for performance benefits. One of the trade-offs of this is that componentWillMount, the other lifecycle event where it might make sense to make an AJAX request, will be “non-deterministic”. What this means is that React may start calling componentWillMount at various times whenever it feels like it needs to. This would obviously be a bad formula for AJAX requests.
You can’t guarantee the AJAX request won’t resolve before the component mounts. If it did, that would mean that you’d be trying to setState on an unmounted component, which not only won’t work, but React will yell at you for. Doing AJAX in componentDidMount will guarantee that there’s a component to update.
这是一个完整的重做示例,使用 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;
我在理解这个 React Native 应用程序中的程序流程时遇到了一些困难。
我已经在整个应用程序中添加了 console.log 语句,以尝试理解。
所以我在构造函数中将状态初始化为lat:0,long:0,err:null和标记:[]。然后在构造函数中,我调用我的 API 方法来获取所有位置并填充标记方法。打印的输出如下:
//来自render方法
[]
[]
[]
//然后构造函数异步方法returns和我们设置标记
{markers: [{title: "A", coordinate: {latitude: 0, longitude: 1}, description: "abc"},
{title: "B", coordinate: {latitude: 0, longitude: 1}, description: "abc"}]}
然后我调用渲染方法,我知道这可能是一种糟糕的做法,但这只是为了尝试调试,希望标记随后在地图上可见。
然而,在此之后,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
ing 组件方法。我会把你所有的异步调用,包括对 navigator
和 fetchAPI
的调用移到 componentDidMount
中,并确保你初始化的任何 state
都不会在 [=22] 上造成任何错误=].正如 Tyler McGinnis 在 this post 中所写:
AJAX requests should go in the componentDidMount lifecycle event.
There are a few reasons for this,
Fiber, the next implementation of React’s reconciliation algorithm, will have the ability to start and stop rendering as needed for performance benefits. One of the trade-offs of this is that componentWillMount, the other lifecycle event where it might make sense to make an AJAX request, will be “non-deterministic”. What this means is that React may start calling componentWillMount at various times whenever it feels like it needs to. This would obviously be a bad formula for AJAX requests.
You can’t guarantee the AJAX request won’t resolve before the component mounts. If it did, that would mean that you’d be trying to setState on an unmounted component, which not only won’t work, but React will yell at you for. Doing AJAX in componentDidMount will guarantee that there’s a component to update.
这是一个完整的重做示例,使用 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;