"Error: you attempted to set the key `latitude` with the value `37.785834` on an object that is meant to be immutable and has been frozen."

"Error: you attempted to set the key `latitude` with the value `37.785834` on an object that is meant to be immutable and has been frozen."

我在 React Native 中使用 navigator.geolocation API 将用户坐标设置为组件状态的一部分,MapView 应该用作 region prop,并且 运行ning getCurrentPosition() 抛出错误。

我不确定如何解决这个问题。该错误表明这是一个不可变性问题,尽管我确定我使用了 letconst 它们应该在的位置。

这是我的初始状态:

this.state = {
      data: {
        name: "Nie powinieneś tego widzieć.",
        address: "Wyślij zrzut ekranu tego widoku do nas na stronie dokosciola.pl w zakładce Kontakt.",
        url: "https://dokosciola.pl",
        coords: {
          latitude: undefined,
          longitude: undefined,
          latitudeDelta: 0.00922 * 1.5,
          longitudeDelta: 0.00421 * 1.5
        },
        hours: ["8:00", "10:00", "12:00"]
      }
};

这就是我使用地理定位的方式 API:

locateUser = () => {
    navigator.geolocation.getCurrentPosition(
      position => {
        let state = this.state;
        state.data.coords.latitude = position.coords.latitude;
        state.data.coords.longitude = position.coords.longitude;
        this.setState(state);
        console.log(this.state);
      },
      error => Alert.alert("Ups!", `Wystąpił wewnętrzny błąd:\n${error}`),
      { enableHighAccuracy: true, timeout: 30000, maximumAge: 5000 }
    );
};

我运行在安装应用程序之前locateUser()函数,所以:

componentWillMount() {
    this.locateUser();
}

这就是我使用 react-native-maps 中的 MapView 组件的方式:

<View style={{ flex: 1 }}>
        <MapView
          style={{ flex: 1 }}
          initialRegion={this.state.data.coords}
          region={this.state.data.coords}
          mapType={"mutedStandard"}
        >
          {data.map(element => {
            return (
              <ChurchMarker
                coords={element.coords}
                key={element.id}
                onPress={() => this.update(element)}
              />
            );
          })}
        </MapView>
</View>

ChurchMarker 是预煮的 Marker,也来自 react-native-maps,而 data - 一个简单的对象数组,模拟潜在的 API 响应:

[
    {
        id: string,
        name: string,
        address: string,
        url: string,
        coords: {
            latitude: number,
            longitude: number
        },
        hours: string[]
    },
    ...
]

我希望 MapView 在应用程序安装时关注用户坐标,但是执行了我在 locateUser() 中指定的错误,并显示以下消息:

Error: you attempted to set the key `latitude` with the value `37.375834` on an object that is meant to be immutable and has been frozen.

之后还有一个警告:

Warning: Failed prop type: The prop `region.latitude` is marked as required in `MapView`, but its value is `undefined`.

经度也一样。这意味着状态没有更新。 对此有任何修复吗?我执行错了什么?

您必须始终使用对象方式更新您的 state。在你的情况下你可以试试这个:

locateUser = () => {
    navigator.geolocation.getCurrentPosition(
      position => {
        this.setState({
         data.coords.latitude: position.coords.latitude,
         data.coords.longitude: position.coords.longitude 
       });
       console.log(this.state)
      },
      error => Alert.alert("Ups!", `Wystąpił wewnętrzny błąd:\n${error}`),
      { enableHighAccuracy: true, timeout: 30000, maximumAge: 5000 }
    );
};

或者如果对于新的 state 你想操纵当前的 state 你必须使用 this.setState

的功能方式

有关详细信息,请阅读 docs 的这一部分。

祝你好运:)

错误消息中清楚地描述了您的问题:您试图在不可变的对象上设置键

当您写 let state = this.state 时,您正在创建对 this.state 的引用,它是不可变的。

因此,当您尝试为 state.data.coords.latitude 分配新值时,您正在改变状态对象,这是非法的。

相反,您应该分两步重构您的代码:

  1. 简化状态对象以减少嵌套(去掉data层):
this.state = {
    name: "Nie powinieneś tego widzieć.",
    address: "Wyślij zrzut ekranu tego widoku do nas na stronie dokosciola.pl w zakładce Kontakt.",
    url: "https://dokosciola.pl",
    coords: {
      latitude: undefined,
      longitude: undefined,
      latitudeDelta: 0.00922 * 1.5,
      longitudeDelta: 0.00421 * 1.5
    },
    hours: ["8:00", "10:00", "12:00"]
}
  1. 创建一个 newCoords 对象并为其设置正确的值,然后使用 setState:
  2. 覆盖 state.coords
locateUser = () => {
    navigator.geolocation.getCurrentPosition(
      position => {
        const newCoords = {}
        newCoords.latitude = position.coords.latitude
        newCoords.longitude = position.coords.longitude
        this.setState({ coords: newCoords })
      },
      error => Alert.alert("Ups!", `Wystąpił wewnętrzny błąd:\n${error}`),
      { enableHighAccuracy: true, timeout: 30000, maximumAge: 5000 }
    );
};