【问题标题】:Our useEffect doesn't call our fetch function我们的 useEffect 没有调用我们的 fetch 函数
【发布时间】: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 是什么?它可能是nullundefined ,并且可能第一个渲染(在效果运行之前)会引发错误,因为代码假定它已设置。
  • 它应该返回一个空对象,但它似乎没有返回任何东西。 useEffect 中的 console.log 根本不记录。更新:我在定义它之后控制台记录了它,它记录了一个空对象。
  • @crashdelta 我将您的代码复制到代码沙箱中:codesandbox.io/s/sharp-framework-pskee 但它似乎没有任何问题,我错过了什么吗?
  • 这很奇怪,因为我的整个应用程序崩溃并声称“天气”未定义。更新:实际上它说'weather.main.temp'的'temp'是未定义的。
  • 我收录了 Insomnia 的数据。

标签: javascript reactjs redux use-effect usecallback


【解决方案1】:

请从useEffect 数组中删除fetchWeather

useEffect(() => {
    console.log('calling fetch');
    
    fetchWeather();
  }, []);

这里的问题是,useEffectfetchWeather 数据被初始化或更新时被调用(当你把[fetchWeather] 放在useEffect 上时)。由于fetchWeather 被初始化并在useEffect 中调用,它什么也没做。 现在,当componentDidMountcomponentDidUdate时调用useEffect函数。

请找到更多使用react hooks的规则here

编辑:问题的真正解决方案(假设 JSX、action 和 reducer 工作正常):

    import { useDispatch, useSelector } from 'react-redux';
    import { setWeather } from '../actions/weatherAction';
    import { useCallback, useEffect, useState } from 'react';
    import Weather from './weather';
    
    function GetWeather() {
      const [fetchData, setFetchData] = useState(false);
      const dispatch = useDispatch();
      {/*Make sure your action, reducer are working perfectly*/}
      const weather = useSelector(state => state.weather);
      
      useEffect(() => {
        if(fetchData) dispatch(setWeather());
      }, [fetchData]);
      
      return (
        <main if={ weather.weather }>
          <Weather weather={ weather }/>
    
          <button onClick={()=>setFetchData(true)}>Go!</button>
        </main>
      )
    }
    
    export default GetWeather;

【讨论】:

  • 不,仍然出现相同的错误,“天气”未定义加上缺少依赖项的 ESlint 错误又回来了。
  • 关于上述解决方案,请确保您的操作、reducer 和 saga 工作正常或将它们发布在问题上。
  • @crashdelta 立即尝试上述解决方案
  • 这似乎也没有解决它,我现在遇到更多缺少依赖项的错误,它说“数据未定义”和“返回数据”是灰色的。
  • 尝试最近的更新,确保你的 action 和 reducer 文件正常工作。
猜你喜欢
  • 2021-08-03
  • 1970-01-01
  • 2020-02-12
  • 2020-10-01
  • 1970-01-01
  • 2020-01-05
  • 1970-01-01
  • 1970-01-01
  • 2020-05-13
相关资源
最近更新 更多