微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我们的 useEffect 不会调用我们的 fetch 函数

如何解决我们的 useEffect 不会调用我们的 fetch 函数

我们正在尝试从 openweather.org 获取数据,我们希望在页面加载时只运行一次的 useEffect 中调用一次获取。我们希望能够从搜索表单中再次调用 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 获取数据。

解决方法

请从 fetchWeather 数组中删除 useEffect

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

这里的问题是,当 useEffect 数据初始化或更新时(当您将 fetchWeather 放在 [fetchWeather] 上)时,会调用 useEffect。由于 fetchWeatheruseEffect 中被初始化和调用,所以它什么也没做。 现在,useEffect 函数在 componentDidMount,componentDidUdate 时被调用。

请找到更多使用 React 钩子 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;

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。