1

我一直在尝试将 redux-sagas 和 redux-toolkit 引入我的项目。似乎当我dispatch(fetchTweets(term))可以看到 Redux DevTools 中的动作触发时。但是当它到达传奇时,什么也没有发生。不知道如何修复它。如果您有任何想法,请告诉我。这是我得到的错误。这是github的链接

在此处输入图像描述

在此处输入图像描述

文件 - configureAppStore.js

import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
import reducer from './reducer';
import toast from './middleware/toast.js';
import websocket from './middleware/websocket.js';
import createSagaMiddleware from 'redux-saga';
import tweetSagas from '../saga/tweet.js';

const configureAppStore = () => {
  const sagaMiddleware = createSagaMiddleware();

  const middlewares = [sagaMiddleware, websocket, toast];
  const middleware = [
    ...getDefaultMiddleware({ thunk: false }),
    ...middlewares,
  ];

  const store = configureStore({
    reducer: reducer,
    middleware: middleware,
  });

  sagaMiddleware.run(tweetSagas);

  return store;
};

export default configureAppStore;

文件 -传奇/tweet.js

import { takeEvery, call, put, fork } from 'redux-saga/effects';
import axios from 'axios';
import * as actions from '../store/action/saga.js';
const port = process.env.REACT_APP_PORT;
const hostname = process.env.REACT_APP_LOCALHOST;
const baseURL = `http://${hostname}:${port}`;

function api({ dispatch }) {
  return function (next) {
    return function* (action) {
      if (action.type !== actions.sagaApiCallBegan.type) return next(action);
      next(action); // 'sagaApiCallBegan' to show in redux dev tools
      const { url, method, onSuccess, onError } = action.payload;
      try {
        const response = yield call(
          async () =>
            await axios.request({
              baseURL: baseURL,
              url,
              method,
            })
        );
        if (onSuccess) yield put({ type: onSuccess, payload: response.data });
      } catch (error) {
        if (onError) yield put({ type: onError, payload: error });
      }
    };
  };
}

function* watchApi() {
  yield takeEvery(actions.sagaApiCallBegan.type, api);
}

export default function* tweetSagas() {
  yield fork(watchApi);
}

文件存储/tweets.js

import { createSlice } from '@reduxjs/toolkit';
import {
  sagaApiCallBegan,
  sagaApiCallSuccess,
  sagaApiCallFailed,
} from './action/saga';
import { webSocketCallBegan, webSocketCallFailed } from './action/websocket.js';
import { normalize } from 'normalizr';
import { tweetSchema } from '../store/Schema/tweet.js';

const initialState = () => ({
  byTweetId: {},
  byUserId: {},
  allTweetIds: [],
});

// action, actionTypes and reducer
const slice = createSlice({
  name: 'tweets',
  initialState: initialState(),
  // reducers
  reducers: {
    tweetAdded: (state, action) => {
      const { entities, result } = normalize(action.payload, tweetSchema);
      Object.assign(state.byTweetId, entities.byTweetId);
      Object.assign(state.byUserId, entities.byUserId);
      state.allTweetIds.push(result);
    },
    tweetStoreReseted: (state) => initialState(),
  },
});

export const { tweetAdded, tweetStoreReseted } = slice.actions;
export default slice.reducer;

// Action creators
export const fetchTweets = (term) =>
  sagaApiCallBegan({
    url: `/setsearchterm/${term}`,
    method: 'get',
    onSuccess: sagaApiCallSuccess.type,
    onError: sagaApiCallFailed.type,
  });

export const fetchTweetsPause = () =>
  sagaApiCallBegan({
    url: '/pause',
    method: 'GET',
    onSuccess: sagaApiCallSuccess.type,
    onError: sagaApiCallFailed.type,
  });

export const getTweet = (message) =>
  webSocketCallBegan({
    message: message,
    onSuccess: tweetAdded.type,
    onError: webSocketCallFailed.type,
  });

文件 -动作/saga.js

import { createAction } from '@reduxjs/toolkit';

export const sagaApiCallBegan = createAction('saga/apiCallBegan');
export const sagaApiCallSuccess = createAction('saga/apiCallSuccess');
export const sagaApiCallFailed = createAction('saga/apiCallFailed');
4

1 回答 1

1

这是解决方案

文件 -传奇/tweet.js

import { takeEvery, call, put, fork } from 'redux-saga/effects';
import axios from 'axios';
import * as actions from '../store/action/saga.js';
const port = process.env.REACT_APP_PORT;
const hostname = process.env.REACT_APP_LOCALHOST;
const baseURL = `http://${hostname}:${port}`;

const fetchApi = async ({ baseURL, url, method }) =>
  await axios.request({
    baseURL: baseURL,
    url: url,
    method: method,
  });

function* api(action) {
  const { url, method, onSuccess, onError } = action.payload;
  const options = {
    baseURL: baseURL,
    url: url,
    method: method,
  };
  try {
    const response = yield call(fetchApi, options);
    if (onSuccess)
      yield put({
        type: onSuccess,
        payload: response.data,
      });
  } catch (error) {
    if (onError) yield put({ type: onError, payload: error });
  }
}

function* watchApi() {
  yield takeEvery(actions.sagaApiCallBegan.type, api);
}

export default function* tweetSagas() {
  yield fork(watchApi);
}
于 2021-01-22T00:29:52.243 回答