在 REACT 中将 setState 设置为另一个状态值

Setting a setState to another state value in REACT

我有一个关于在 class 组件中使用状态的 React 练习。当我编写如下代码时,我的解决方案运行良好:

import React from "react";
import "./App.css";

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = { lat: null, errorMessage: "" };

    window.navigator.geolocation.getCurrentPosition(
      (position) => this.setState({ lat: position.coords.latitude }),
      (err) => this.setState({ errorMessage: err.message })
    );
  }
  render() {
    if (this.state.lat && !this.state.errorMessage) {
      return <div>Latitude: {this.state.lat}</div>;
    } else if (!this.state.lat && this.state.errorMessage) {
      return <div>Erroe: {this.state.errorMessage}</div>;
    } else {
      return <div>Latitude: Loading...</div>;
    }
  }
}

export default App;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

但是当我用另一种方式写的时候,没有报错但是没有输出

class App extends React.Component {
  constructor(props) {
    super(props);

    this.state = { lat: null, errorMessage: "", message: "" };

    window.navigator.geolocation.getCurrentPosition(
      (position) => this.setState({ lat: position.coords.latitude }),
      (err) => this.setState({ errorMessage: err.message })
    );
    if (this.state.lat && !this.state.errorMessage) {
      this.setState({ message: "Latitude: " + this.state.lat });
    } else if (!this.state.lat && this.state.errorMessage) {
      this.setState({ message: "Error: " + this.state.errorMessage });
    } else {
      this.setState({ message: "Loading..." });
    }
  }
  render() {
    return <div> {this.state.message} </div>;
  }
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

第二种方式有什么问题?

两个主要问题:

1) setState是异步的

即使第二个问题不存在,你也不能在调用 setState 后立即反省状态;状态尚未设置。

2) getCurrentPosition是异步的

getCurrentPosition 的回调将在未来的不确定时间执行。构造函数继续 运行,在 getCurrentPosition 可能调用其回调之前调用 setState(基于当前状态,初始化为 null 和空字符串)。

(并且在构造函数本身中调用 setState 的理由为零(与 getCurrentPosition 的回调相反,这很好),您可以直接设置状态首先初始化它。

setState 是异步的。 this.state 在下一次渲染中获取新值,但您正试图立即使用它。

如果您想将消息存储在状态中,您可以在传递给 getCurrentPosition 的回调中执行此操作,最好在 ComponentDidMount 中处理所有这些,而不是在构造函数中处理。

import { Component } from "react";
import "./styles.css";

export default class App extends Component {
  constructor(props) {
    super(props);

    this.state = { lat: null, errorMessage: "", message: "" };
  }

  componentDidMount() {
    window.navigator.geolocation.getCurrentPosition(
      (position) => {
        const lat = position.coords.latitude;
        this.setState({ lat, message: `Latitude: ${lat}` });
      },
      (err) =>
        this.setState({
          errorMessage: err.message,
          message: `Error: ${err.message}`
        })
    );
  }

  render() {
    return <div> {this.state.message} </div>;
  }
}