【发布时间】:2021-08-17 06:09:45
【问题描述】:
我们正在尝试从 openweather.org 获取数据,我们希望在加载页面时只运行一次的 useEffect 中调用 fetch。我们希望能够从搜索表单中再次调用 fetch,因此为了避免重复代码,我们不希望我们的 fetch 在 useEffect 函数中。
import { useDispatch, useSelector } from 'react-redux';
import { setWeather } from '../actions/weatherAction';
import { useCallback, useEffect } from 'react';
import Weather from './weather';
function GetWeather() {
console.log('what up yo?') // 1. Logs
const dispatch = useDispatch();
const weather = useSelector(state => state.weather);
console.log(weather) // 2. Logs an empty object as expected
// async function fetchWeather() {
// console.log('fetching')
// const response = await fetch('https://api.openweathermap.org/data/2.5/weather?q=stockholm&appid=1dc27327c1655e53a85e6e5a889fccee');
// console.log('response:', response);
// const data = await response.json();
// console.log('data:', data);
// dispatch(setWeather(data));
// } This is what we initially tried together with useEffect(() => { fetchWeather() }, []) which seemed to work sometimes but not every time.
const fetchWeather = useCallback(() => {
console.log('fetching'); // 4. Does not log!
return fetch('https://api.openweathermap.org/data/2.5/weather?q=stockholm&appid=1dc27327c1655e53a85e6e5a889fccee')
.then(response => response.json())
.then(data => dispatch(setWeather(data)))
}, [dispatch])
// useEffect(() => {
// console.log('useEffect: ', weather);
// }, [weather]);
useEffect(() => {
console.log('calling fetch'); // 3. Does not log!
fetchWeather();
}, [fetchWeather]);
return (
<main if={ weather.weather }>
<Weather weather={ weather }/>
<button onClick={ fetchWeather }>Go!</button>
</main>
)
}
export default GetWeather;
减速机:
const initState = {
weather: {}
};
export const weatherReducer = (state = initState, action) => {
switch (action.type) {
case 'SET_WEATHER':
return {
...state,
weather: action.payload
};
default:
return state;
}
};
动作:
export const setWeather = (weather) => {
return {
type: 'SET_WEATHER',
payload: weather
};
};
来自失眠症的数据:
{
"coord": {
"lon": 2.159,
"lat": 41.3888
},
"weather": [
{
"id": 800,
"main": "Clear",
"description": "clear sky",
"icon": "01d"
}
],
"base": "stations",
"main": {
"temp": 291.36,
"feels_like": 291.01,
"temp_min": 288.47,
"temp_max": 293.7,
"pressure": 1017,
"humidity": 68
},
"visibility": 10000,
"wind": {
"speed": 0.45,
"deg": 307,
"gust": 4.02
},
"clouds": {
"all": 0
},
"dt": 1622266137,
"sys": {
"type": 2,
"id": 2003688,
"country": "ES",
"sunrise": 1622262117,
"sunset": 1622315758
},
"timezone": 7200,
"id": 3128760,
"name": "Barcelona",
"cod": 200
}
存储(index.js):
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import { createStore } from 'redux';
import { Provider } from 'react-redux';
import { weatherReducer } from './reducers/weatherReducer';
const store = createStore(weatherReducer);
console.log(store);
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>,
document.getElementById('root')
);
reportWebVitals();
在阅读有关此主题的另一个问题后,我们尝试使用 useCallback,但无济于事。不过,我们可以使用 Insomnia 获取我们的数据。
【问题讨论】:
-
第一次渲染时
weather是什么?它可能是null或undefined,并且可能第一个渲染(在效果运行之前)会引发错误,因为代码假定它已设置。 -
它应该返回一个空对象,但它似乎没有返回任何东西。 useEffect 中的 console.log 根本不记录。更新:我在定义它之后控制台记录了它,它记录了一个空对象。
-
@crashdelta 我将您的代码复制到代码沙箱中:codesandbox.io/s/sharp-framework-pskee 但它似乎没有任何问题,我错过了什么吗?
-
这很奇怪,因为我的整个应用程序崩溃并声称“天气”未定义。更新:实际上它说'weather.main.temp'的'temp'是未定义的。
-
我收录了 Insomnia 的数据。
标签: javascript reactjs redux use-effect usecallback