React,setstate 不会在一个变量的 useEffect 函数内部激活,适用于另一个变量
React, setstate does not activate inside useEffect function for one variable, works for another
我正在尝试显示一张地图,其中包含用户当前位置以及一些其他几何图形。我可以访问这些数据并显示它们,但是当需要显示另一个页面时,我想取消订阅位置更新。为此,我需要一个 ID(根据 navigator.geolocation
的文档)。我试图将此 ID 存储在状态变量中,但由于某种原因我无法在我的 useEffect
函数中设置此 ID。
令人费解的是,我还将几何数据存储在一个状态变量中,我可以从 useEffect
循环内部设置它。我只是无法弄清楚 features
和 watcherId
状态变量之间有什么区别。当我 运行 此代码时 waId
被设置,但观察者 ID 始终保持 -1
,因此我无法使用它取消订阅位置更改事件。
import React, { useState, useEffect } from 'react';
import GeoJSON from 'ol/format/GeoJSON';
import Feature from 'ol/Feature';
import {Point} from 'ol/geom';
import {transform, fromLonLat} from 'ol/proj';
import MapWrapper from './Base_MapWrapper';
function Card_Map(props) {
const [ features, setFeatures ] = useState([]);
const [ watcherId, setWatcherId ] = useState(-1);
useEffect( () => {
const wktOptions = {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}
const parsedFeatures = new GeoJSON().readFeatures(props.jsonData, wktOptions);
let waId = -1;
if (navigator.geolocation) {
console.log('location available');
waId = navigator.geolocation.watchPosition(function(position) {
let coorArr = [position.coords.longitude, position.coords.latitude];
let newCoors = transform(coorArr, 'EPSG:4326', 'EPSG:3857');
let fPoint = new Feature({
geometry: new Point(newCoors)
});
let theFeatures = [fPoint, ...parsedFeatures];
setFeatures(theFeatures);
});
console.log(waId);
setWatcherId(waId);
}
else {
setFeatures(parsedFeatures);
}
console.log(watcherId);
//this is the destructor
return () => {
if (watcherId != -1)
{
navigator.geolocation.clearWatch(watcherId);
}
}
},[]);
return (
<div>
<MapWrapper features={features} cssClass={props.cssClass} />
</div>
)
}
export default Card_Map
您的问题是您正在尝试使用 watcherId
,它会在调用 setWatcherId
.
之前保留值的引用
我很确定你有一条警告说你应该使用 watcherId
作为依赖项,但这会触发另一个 re-render 和一个新的集合等等。
你在这里实际上不需要状态,你可以只使用 waId
所以你应该得到以下结果:
function Card_Map(props) {
const [ features, setFeatures ] = useState([]);
useEffect( () => {
const wktOptions = {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}
const parsedFeatures = new GeoJSON().readFeatures(props.jsonData, wktOptions);
let waId = -1;
if (navigator.geolocation) {
console.log('location available');
waId = navigator.geolocation.watchPosition(function(position) {
let coorArr = [position.coords.longitude, position.coords.latitude];
let newCoors = transform(coorArr, 'EPSG:4326', 'EPSG:3857');
let fPoint = new Feature({
geometry: new Point(newCoors)
});
let theFeatures = [fPoint, ...parsedFeatures];
setFeatures(theFeatures);
});
}
else {
setFeatures(parsedFeatures);
}
//this is the destructor
return () => {
if (waId != -1)
{
navigator.geolocation.clearWatch(waId);
}
}
},[]);
return (
<div>
<MapWrapper features={features} cssClass={props.cssClass} />
</div>
)
}
如果你确实需要在另一个地方使用id
,保持状态,但仍然在清理函数中使用waId
。
我正在尝试显示一张地图,其中包含用户当前位置以及一些其他几何图形。我可以访问这些数据并显示它们,但是当需要显示另一个页面时,我想取消订阅位置更新。为此,我需要一个 ID(根据 navigator.geolocation
的文档)。我试图将此 ID 存储在状态变量中,但由于某种原因我无法在我的 useEffect
函数中设置此 ID。
令人费解的是,我还将几何数据存储在一个状态变量中,我可以从 useEffect
循环内部设置它。我只是无法弄清楚 features
和 watcherId
状态变量之间有什么区别。当我 运行 此代码时 waId
被设置,但观察者 ID 始终保持 -1
,因此我无法使用它取消订阅位置更改事件。
import React, { useState, useEffect } from 'react';
import GeoJSON from 'ol/format/GeoJSON';
import Feature from 'ol/Feature';
import {Point} from 'ol/geom';
import {transform, fromLonLat} from 'ol/proj';
import MapWrapper from './Base_MapWrapper';
function Card_Map(props) {
const [ features, setFeatures ] = useState([]);
const [ watcherId, setWatcherId ] = useState(-1);
useEffect( () => {
const wktOptions = {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}
const parsedFeatures = new GeoJSON().readFeatures(props.jsonData, wktOptions);
let waId = -1;
if (navigator.geolocation) {
console.log('location available');
waId = navigator.geolocation.watchPosition(function(position) {
let coorArr = [position.coords.longitude, position.coords.latitude];
let newCoors = transform(coorArr, 'EPSG:4326', 'EPSG:3857');
let fPoint = new Feature({
geometry: new Point(newCoors)
});
let theFeatures = [fPoint, ...parsedFeatures];
setFeatures(theFeatures);
});
console.log(waId);
setWatcherId(waId);
}
else {
setFeatures(parsedFeatures);
}
console.log(watcherId);
//this is the destructor
return () => {
if (watcherId != -1)
{
navigator.geolocation.clearWatch(watcherId);
}
}
},[]);
return (
<div>
<MapWrapper features={features} cssClass={props.cssClass} />
</div>
)
}
export default Card_Map
您的问题是您正在尝试使用 watcherId
,它会在调用 setWatcherId
.
我很确定你有一条警告说你应该使用 watcherId
作为依赖项,但这会触发另一个 re-render 和一个新的集合等等。
你在这里实际上不需要状态,你可以只使用 waId
所以你应该得到以下结果:
function Card_Map(props) {
const [ features, setFeatures ] = useState([]);
useEffect( () => {
const wktOptions = {
dataProjection: 'EPSG:4326',
featureProjection: 'EPSG:3857'
}
const parsedFeatures = new GeoJSON().readFeatures(props.jsonData, wktOptions);
let waId = -1;
if (navigator.geolocation) {
console.log('location available');
waId = navigator.geolocation.watchPosition(function(position) {
let coorArr = [position.coords.longitude, position.coords.latitude];
let newCoors = transform(coorArr, 'EPSG:4326', 'EPSG:3857');
let fPoint = new Feature({
geometry: new Point(newCoors)
});
let theFeatures = [fPoint, ...parsedFeatures];
setFeatures(theFeatures);
});
}
else {
setFeatures(parsedFeatures);
}
//this is the destructor
return () => {
if (waId != -1)
{
navigator.geolocation.clearWatch(waId);
}
}
},[]);
return (
<div>
<MapWrapper features={features} cssClass={props.cssClass} />
</div>
)
}
如果你确实需要在另一个地方使用id
,保持状态,但仍然在清理函数中使用waId
。