状态未在地理定位功能中使用 setState 进行更新
Posted
技术标签:
【中文标题】状态未在地理定位功能中使用 setState 进行更新【英文标题】:State is not updating using setState in geolocation function 【发布时间】:2020-02-13 05:51:03 【问题描述】:当我从地理位置 api 获取坐标时,我正在尝试更新状态。但是状态没有更新。我在 setState 中放置了回调来检查更新坐标的内容,它是未定义的。 但我不知道应该把这个 setState 放在哪里来更新实际坐标。
class App extends React.Component
constructor(props)
super(props);
// App State
this.state =
lat: 0,
lng: 0
;
// ComponentDIDMount
componentDidMount()
// Get Data from json file
$.getJSON("../resturants.json", data =>
this.setState(
resturantsList: data
);
);
// Get location of user
let success = position =>
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
console.log(latitude, longitude);
this.setState(
lat: latitude,
lng: longitude
,
() => console.log(latitude, longitude)
);
console.log(this.state);
;
function error()
console.log("Unable to retrieve your location");
navigator.geolocation.getCurrentPosition(success, error);
// Api call for resturants data
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=$this.state.lat,$this.state.lng&radius=3000&type=restaurant&key=apikey`;
console.log(url);
fetch(proxyurl + url)
.then(res => res.json())
.then(
result =>
console.log(result.results);
let apiResturants = result.results;
let allResturants = this.state.resturantsList.concat(
...apiResturants
);
this.setState(
resturantsList: allResturants
);
,
error =>
console.log("error");
);
// Render function for app component
render()
【问题讨论】:
您不得使用this.state=...
初始化状态
并且状态更新是异步的,请查看官方文档
你能告诉我这个异步更新是如何影响状态更新的吗?
查看reactjs.org/docs/…
好吧,如果您的日志未定义,那么显然这里的问题不是 React 或 setState,而是您的 API 没有返回您认为返回的内容。登录position
看看它是否提供了什么。如果没有,您需要查看您的 navigator.geolocation.getCurrentPosition
以查看您是否正确使用它。
【参考方案1】:
这是解决方案:
const getData = () =>
// Api call for resturants data
const proxyurl = "https://cors-anywhere.herokuapp.com/";
const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=$this.state.lat,$this.state.lng&radius=3000&type=restaurant&key=apikey`;
console.log(url);
fetch(proxyurl + url)
.then(res => res.json())
.then(
result =>
console.log(result.results);
let apiResturants = result.results;
let allResturants = this.state.resturantsList.concat(
...apiResturants
);
this.setState(
resturantsList: allResturants
);
,
error =>
console.log("error");
);
componentDidMount()
const success = position =>
this.setState(lat: position.latitude, long: position.longitude, () =>
this.getData();
)
setState 是异步操作,表示状态更新将在以后完成。如果要检查状态何时更新,可以使用第二个参数。
this.setState(lat:latitude, long: longitude, () => console.log(this.state));
第二个回调会告诉你确切的问题,因为一旦状态更新完成就会调用它。
【讨论】:
好的,现在我看到回调也返回了准确的位置,但是我如何让 setState 在他获得准确的值时进行状态更新。即纬度/经度 如果您在控制台中记录回调中的状态并获得正确的结果,这意味着状态已更新。 你是绝对正确的,但我有一个 api 调用,它从状态中获取位置变量。即使在状态更新后它也不会发出请求,这让我认为状态没有更新。 const url =https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=$this.state.lat,$this.state.lng&radius=3000&type=restaurant&key=apikey
您正在为 url 使用状态数据,但这不会自动触发请求。状态更新只会触发重新渲染。您必须在 componentDidMount 或其他地方进行请求调用。或者,如果我遗漏了什么,您可以再解释一下。【参考方案2】:
不要进行异步调用,也不要在 React 组件的 constructor 内调用 this.setState
。
你不应该在constructor()中调用setState()。
使用componentDidMount
生命周期函数来获取数据和更新状态。
constructor(props)
super(props);
// App State
this.state =
lat: 0,
lng: 0
;
componentDidMount()
// Get location of user
const success = position =>
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
console.log(latitude, longitude);
this.setState(
lat: latitude,
lng: longitude
);
;
const error = () =>
console.log("Unable to retrieve your location");
;
navigator.geolocation.getCurrentPosition(success, error);
状态更新是异步的
React 状态更新是异步的,并在当前渲染周期结束时排队等待处理。您正在访问 当前 渲染周期的状态值,而不是下一个周期的状态值。将 navigator.geolocation.getCurrentPosition
调用保存的 lat 和 long 值移动到 componentDidMount
的函数范围中,并在后面的 fetch
中使用它们,而不是使用状态 lat
和 lng
。
componentDidMount()
// Get Data from json file
$.getJSON("../resturants.json", data =>
this.setState(
resturantsList: data
);
);
// Get location of user
// Move latitude and longitude to function scope
let latitude = 0;
let longitude = 0;
let success = position =>
// cache values
latitude = position.coords.latitude;
longitude = position.coords.longitude;
console.log(latitude, longitude);
this.setState(
lat: latitude,
lng: longitude
,
() => console.log(latitude, longitude)
);
console.log(this.state);
;
function error()
console.log("Unable to retrieve your location");
navigator.geolocation.getCurrentPosition(success, error);
// Api call for resturants data
const proxyurl = "https://cors-anywhere.herokuapp.com/";
// use cached lat & long values
const url = `https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=$
latitude
,$longitude&radius=3000&type=restaurant&key=apikey`;
console.log(url);
fetch(proxyurl + url)
.then(res => res.json())
.then(
result =>
console.log(result.results);
let apiResturants = result.results;
let allResturants = this.state.resturantsList.concat(
...apiResturants
);
this.setState(
resturantsList: allResturants
);
,
error =>
console.log("error");
);
【讨论】:
谢谢哥们,ComponentDidMount 就在那里。我只是一开始没有包括它。我的错。 @Mehmood 更新了答案,解释了为什么以后不能在同一个函数中访问状态更新,并提供了一个可能的解决方案。 您好,谢谢。我有我的答案。查看@oneJeet 答案。 @user1864070 谢谢。是的,我不认为链接setState
回调以进行进一步 状态更新是一个好的模式,这就是组件生命周期函数的用途。【参考方案3】:
由于你在一个胖箭头函数中,你可以使用 let self = this
重新定义你的 this,然后使用 self.setState 代替
【讨论】:
这条线在哪里?让自我=这个。内部成功函数?以上是关于状态未在地理定位功能中使用 setState 进行更新的主要内容,如果未能解决你的问题,请参考以下文章