#reactjs #state #rerender
#reactjs #состояние #повторный рендеринг
Вопрос:
У меня есть компонент класса ReactJS со следующим конструктором:
constructor(props) {
super(props);
this.state = {
// Defaults (London)
latitude: 51.509865,
longitude: -0.118092,
userAddress: null
};
this.getCoordinates = this.getCoordinates.bind(this);
}
Затем я пытаюсь получить координаты пользователя и сохранить их в состоянии:
// On component initialisation, get the users location in co-ordinates and set the state accordingly
componentDidMount() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(this.getCoordinates, this.handleLocationError);
} else {
alert("Geolocation is not supported by this browser.");
}
}
getCoordinates(position) {
this.setState({
latitude: position.coords.latitude,
longitude: position.coords.longitude
})
}
Я передаю координаты пользователей дочерней функции, которая отображает на экране карту погоды с текущей температурой в местоположении пользователя.
Функция рендеринга:
render() {
(some code)
<div><CreateWeatherCard lat={this.state.latitude} long={this.state.longitude} /></div>
(some code)
}
Функция для создания карты погоды использует координаты пользователей в качестве реквизитов, использует их в вызове API POST-запроса и затем должна отображать температуру в текущем местоположении пользователя на экране
function CreateWeatherCard(props) {
const classes = cardStyles();
let [currentTemp, setCurrentTemp] = React.useState([]);
// console.log(props.lat)
React.useEffect(() => {
async function fetchData() {
const request = await axios.post('/weatheratcoords/', {
lat: props.lat,
long: props.long
});
// console.log(request);
// console.log(request.data.currentTemp);
setCurrentTemp(request.data.currentTemp);
return request;
}
fetchData();
}, []);
return
blah blah
Но поскольку я запускаю серверную часть локально, я вижу, что получаю только один вызов API с координатами по умолчанию из конструктора состояния. Я никогда не получаю второй вызов с обновленными координатами. Я знаю, что состояние успешно обновляется, поскольку я вижу свои собственные координаты lat / long в состоянии компонента в инструментах React dev.
Я понимаю, что изменение состояния должно вызвать повторный рендеринг, который, в свою очередь, должен создать новый вызов API с правильными пользовательскими координатами? Может кто-нибудь помочь мне понять, почему этого не происходит? Спасибо!
Ответ №1:
Существует проблема с вашим useEffect()
.
Вы написали это так:
React.useEffect(() => {
async function fetchData() {
const request = await axios.post('/weatheratcoords/', {
lat: props.lat,
long: props.long
});
// console.log(request);
// console.log(request.data.currentTemp);
setCurrentTemp(request.data.currentTemp);
return request;
}
fetchData();
}, []);
Второй параметр — пустой массив, что означает useEffect()
, что он будет выполнен только один раз.
Решение
Поскольку вы передаете значения с использованием реквизита дочернему компоненту, поэтому при изменении реквизита useEffect()
выполняется. Для этого передайте реквизиты внутри массива в вашем useEffect()
качестве второго параметра.
Сделайте это так:
React.useEffect(() => {
async function fetchData() {
const request = await axios.post('/weatheratcoords/', {
lat: props.lat,
long: props.long
});
// console.log(request);
// console.log(request.data.currentTemp);
setCurrentTemp(request.data.currentTemp);
return request;
}
fetchData();
}, [props]);
Комментарии:
1. Большое вам спасибо. Это решило проблему. Я проведу еще несколько исследований функции useEffect, чтобы убедиться, что я использую ее правильно в будущем! Спасибо за краткое объяснение.