【问题标题】:dispatching action in redux-saga is not fetching dataredux-saga 中的调度操作未获取数据
【发布时间】:2021-07-09 01:37:33
【问题描述】:

我正在研究 redux-saga,我想从以下位置获取数据:

https://jsonplaceholder.typicode.com/posts

在我的 redux 文件夹中,我有以下内容:

(可以在这个github仓库中查看 https://github.com/jotasenator/redux-saga-fetching-example/tree/main/src)

\src\redux\api.js

import axios from 'axios'

export const loadPostApi = async () => {
    await axios.get(`https://jsonplaceholder.typicode.com/posts`)
}

对相关地址的获取请求

src\redux\app.actions.js

export const loadPostStart = () => ({
    type: 'LOAD_POST_START',

})
export const loadPostSuccess = (posts) => ({
    type: 'LOAD_POST_SUCCESS',
    payload: posts,
})
export const loadPostFail = (error) => ({
    type: 'LOAD_POST_FAIL',
    payload: error,
})

这些是动作函数

src\redux\app.reducer.js

const INITIAL_STATE = {
    loading: false,
    posts: [],
    errors: null,
}

export const appReducer = (state = INITIAL_STATE, action) => {
    switch (action.type) {
        case 'LOAD_POST_START':
            return {
                ...state,
                loading: true,
            }
        case 'LOAD_POST_SUCCESS':
            return {
                ...state,
                posts: action.payload,
                loading: false,
            }
        case 'LOAD_POST_FAIL':
            return {
                ...state,
                errors: action.payload,
                loading: false,
            }

        default:
            return state;
    }
}

获取、更新状态的reducer,

src\redux\counterReducer.js

import { types } from "./types";

const initialState = {
    value: 0
}

export const counterReducer = (state = initialState, action) => {
    switch (action.type) {
        case types.adicionar:
            return {
                ...state,
                value: state.value + 1
            }

        case types.resetear:
            return {
                ...state,
                value: 0
            }

        case types.restar:
            return {
                ...state,
                value: state.value - 1
            }

        default:
            return state
    }
}

这是counter app的reducer,方法不同,类型被隔离在另一个文件中

src\redux\rootReducer.js

import { combineReducers } from 'redux'
import { counterReducer } from './counterReducer'
import { appReducer } from './app.reducer'

export const rootReducer = combineReducers({
    counterReducer,
    appReducer
})

用于收集 reducer 的 rootReducer

src\redux\sagas.js

import { put, takeLatest, call } from 'redux-saga/effects'
import { loadPostApi } from './api'
import { loadPostFail, loadPostSuccess } from './app.actions'

export function* onLoadPostStartAsync() {
    try {
        const response = yield call(loadPostApi)
        yield put(loadPostSuccess(response.data))
    } catch (error) {
        yield put(loadPostFail(error))

    }
}

export function* onLoadPost() {
    yield takeLatest('LOAD_POST_START', onLoadPostStartAsync)

}

export default function* rootSaga() {
    yield ([
        onLoadPost(),
    ])
}

saga onLoadPostStartAsync 在 rootSaga 中由 saga onLoadPost 调用

src\redux\store.js

import { applyMiddleware, compose, createStore } from "redux";
import createSagaMiddleware from 'redux-saga'

import { rootReducer } from "./rootReducer";

import rootSaga from "./sagas";

const sagaMiddleware = createSagaMiddleware()

const composeEnhancers = (typeof window !== 'undefined' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose

const enhancer = composeEnhancers(applyMiddleware(sagaMiddleware))

export const store = createStore(rootReducer, enhancer)

sagaMiddleware.run(rootSaga)

这是带有 redux_devtool_extension、reducers 和运行 rootSaga 的商店

src\redux\types.js

export const types = {
    adicionar: 'ADICIONAR',
    resetear: 'RESETEAR',
    restar: 'RESTAR'
}

这些是 counterApp reducer 的类型

src\Counter.js

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'

export const Counter = () => {

  const dispatch = useDispatch()
  const { value } = useSelector(state => state.counterReducer)

  const handleAdicionar = () => {
    dispatch({ type: 'ADICIONAR' })
  }
  const handleResetear = () => {
    (value !== 0) && dispatch({ type: 'RESETEAR' })
  }
  const handleRestar = () => {
    dispatch({ type: 'RESTAR' })
  }
  console.log(value)
  return (
    <div>
      <button onClick={handleAdicionar}>Adicionar</button>
      {' '}
      <button onClick={handleResetear}>Resetear</button>
      {' '}
      <button onClick={handleRestar}>Restar</button>
      <hr />

    </div>
  )
}

这是 Counter 组件,它工作正常

src\Fetching.js

import React from 'react'
import { useDispatch, useSelector } from 'react-redux'
import { loadPostStart } from './redux/app.actions'


export const Fetching = () => {
    const dispatch = useDispatch()

    const fetchPost = () => {
        dispatch(loadPostStart())
    }

    const state = useSelector(state => state.appReducer)
    console.log(state)


    return (
        <>
            <h1>Fetching from https://jsonplaceholder.typicode.com</h1>
            <button onClick={fetchPost}>Fetching</button>
            {
                !state.loading && state.posts.map((post) => (
                    <li key={post.id}><h2>{post.title}</h2></li>

                ))
            }

        </>
    )
}

Fetching 组件点击按钮调用 fetchPost 函数,该函数调度 loadPostStart() 函数,这与调度 {type: 'LOAD_POST_START'} 相同,但点击时这里没有任何反应,这里没有任何内容https://jsonplaceholder.typicode.com/posts

src\index.js

import React from 'react';
import ReactDOM from 'react-dom';
import { store } from './redux/store';
import { Provider } from "react-redux";
import { Unificator } from './Unificator';

ReactDOM.render(
  <Provider store={store}>
    <Unificator />
  </Provider>,


  document.getElementById('root')
);

组件 Unificator 有 Counter 和 Fetching 组件

src\Unificator.js

import React from 'react'
import { Counter } from './Counter'
import { Fetching } from './Fetching'

export const Unificator = () => {
    return (
        <div>
            <Counter />
            <Fetching />

        </div>
    )
}


如你所见,大概有两个reducer,一个是著名的counter,另一个是fetching issue,不知道是怎么回事,没有获取数据

显然,我在这里做错了......看不到哪里

【问题讨论】:

  • 传奇会被触发吗?
  • 我怎么知道?,我可以说不,但是调度是好的,可以在redux-devTools看到它

标签: reactjs react-redux redux-saga


【解决方案1】:

Axio 返回 Promise,你需要捕获它并返回。请尝试替换以下代码。


export const loadPostApi = async () => {
    await axios.get(`https://jsonplaceholder.typicode.com/posts`)
    .then((response) => {
         console.log('Response', response);
         return response;
    })
    .catch((error) => {
         console.log('error', error);
    })
}

【讨论】:

  • 什么也没发生。我认为公平地说 loadPostApi 没有被调用
  • 请检查开发工具->网络选项卡是否正在发生 api 调用。
  • 没有发生
  • 我认为你需要将 saga 和 reducer 注入到你的组件中。请尝试在您的组件中使用 useInjectorSaga 和 useInjectorReducer。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2020-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多