为什么在 ReactNative 中 render() 被调用两次?

IT技术 javascript reactjs react-native
2021-05-17 01:03:55

我目前正在尝试使用一个屏幕制作一个应用程序,其中屏幕的背景由以用户当前坐标为中心的地图占据。在下面的代码中,我在 App 类组件的状态中将经度和经度保存为 null。然后,我使用继承的方法“componentDidMount()”更新用户当前位置的状态,最后在 render() 中我使用 this.state.latitude 和 this.state.longitude 来通知纬度和经度的值地图视图。

代码无法编译。使用console.log,我将问题隔离为render() 被调用两次,我的console.log 语句首先将空值输出到控制台,然后输出用户的当前位置。

所以两个问题。

1)为什么console.log会向控制台输出两次不同的值,一次是传入的状态值,一次是componentDidMount()更新的状态值?

2) 如何运行函数 navigator.geolocation.getCurrentPosition() 来保存用户的当前位置并将其传递给 MapView 以便代码首先编译?

export default class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = { latitude: null, longitude: null };
  }

  componentDidMount() {
    navigator.geolocation.getCurrentPosition(position => {
      this.setState({
        latitude: position.coords.latitude,
        longitude: position.coords.longitude,
      });
    });
  }

  render() {
    return (
      <View style={styles.container}>
        <MapView
          style={styles2.map}
          initialRegion={{
            latitude: this.state.latitude,
            longitude: this.state.longitude,
            latitudeDelta: 0.0922,
            longitudeDelta: 0.0421,
          }}
        />

        {console.log(this.state.latitude)}
        {console.log(this.state.longitude)}
      </View>
    );
  }
}
3个回答

每当您的组件通过state或props更新时,React 都会重新渲染在您componentDidMount()正在调用setState(),因此在此之后的某个时间点(因为它是异步的),您的组件将需要为新组件更新,state以便再次呈现。

第一个render()发生在您的组件安装时。在这里,您将看到状态的初始值latitudelongitude状态。

你的组件已经安装后,你的通话setState()将更新state与新valuelatitude,并longitude让你的组件将render()第二次在这里您将看到的新的value观latitudelongitude

编辑:

如果你想避免latitudelongitude(注意。它仍然会渲染两次)的第一次显示,你可以有条件地渲染即

render() {
    if(!this.state.longitude) {
      return <View>Loading...</View>;
    }

    return (
      <View style={styles.container}>
        <MapView
          style={styles2.map}
          initialRegion={{
            latitude: this.state.latitude,
            longitude: this.state.longitude,
            latitudeDelta: 0.0922,
            longitudeDelta: 0.0421,
          }}
        />
      </View>
    );
}

当 state 或 props 中的值发生变化时,总是调用 render 方法

#2 很简单——你挂载了组件(render 1),然后“componentDidMount”在组件“did mount”之后运行,然后等待返回的位置,即render 2。请记住,React,按照设计,将渲染很多

前提是它需要通常非常昂贵的东西(更新整个 DOM),而是管理自己的“虚拟 DOM”,更新成本非常低。昂贵的 DOM 更新被优化为仅更新更改的部分,因此您可以自由地重新运行render()很多。有时您会发现渲染方法很慢,您可能需要返回并优化,但它们是例外,而不是规则。

#1 实际上描述了您的代码完美运行。getCurrentPosition是异步的(通过它的回调),它正确地获得了纬度/经度。如果只是简单地渲染它就抛出错误,那就是你的 JSX 有问题。尝试简化它,例如<p>{this.state.longitude}, {this.state.latitude}</p>查看它是否呈现正确的值,然后从那里构建。