javascript - 使用 React,为什么 redux saga 不拦截 Action ?

标签 javascript reactjs redux-saga

我是 redux-saga 的新手,正在尝试获取 simple demo working 调用 API 并将响应数据发送到 reducer,以便将其保存到 store。据我了解,redux-saga 流程应该按如下方式工作。

  1. 组件调用 Action 创建器
  2. 然后 Action 创建者使用特定类型发出 Action
  3. watcher sagas 全部监听发出的任何 Action 并拦截它正在监听的 Action 。然后调用适当的 worker saga。
  4. worker saga 进行 API 调用,并使用操作类型和负载将操作分派(dispatch)给 reducer。
  5. reducer 监听任何已分派(dispatch)的操作,如果匹配,则使用提供的数据更新存储中的状态。


enter image description here


我已经制定了我的代码来遵循该流程,但事情不太正常。让我展示我的代码,然后我将详细说明问题。


组件/PostsIndex.js

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '../actions';

class PostsIndex extends Component {
  componentDidMount() {
    this.props.fetchPosts();
  }

  renderPosts() {
    console.log(this.props.posts);
  }

  render() {
    return (
      <div>
        {this.renderPosts()}
      </div>
    );
  }
}

const mapStateToProps = state => ({
    posts: state.posts
  });

export default connect(mapStateToProps, { fetchPosts })(PostsIndex);


actions/index.js

import axios from 'axios';

export const FETCH_POSTS = 'FETCH_POSTS';

export const fetchPosts = () => {
  console.log('fetchPosts() in actions');

  return {
    type: FETCH_POSTS
  };
};


sagas/index.js

import 'regenerator-runtime/runtime';
import { call, put, takeEvery, takeLatest } from 'redux-saga/effects';
import axios from 'axios';
import { FETCH_POSTS } from '../actions';

const ROOT_URL = 'https://reduxblog.herokuapp.com/api';
const API_KEY = '?key=asdsd1234';

// Watcher sagas
// Listen for an action and run the appropriate Worker saga
export function* watchFetchPosts() {
  yield takeEvery(FETCH_POSTS, workFetchPosts);
}

// Worker sagas
// Respond to the actions that are caught by the watcher sagas
export function* workFetchPosts() {
  try {
    console.log('workFetchPosts() in sagas');

    // Try to call the API
    console.log('Attempting to call the posts API');
    const uri = `${ROOT_URL}/posts${API_KEY}`;
    const response = yield call(axios.get, uri);
    console.log('Fetched Posts Response in saga worker: ', response);
    yield put({
      type: FETCH_POSTS,
      payload: response
    });
  } catch (error) {
    // Act on the error
    console.log('Request failed! Could not fetch posts.');
    console.log(error);
  }
}

// Root sagas
// Single entry point to start all sagas at once
export default function* rootSaga() {
  console.log('redux saga is running');
  yield [watchFetchPosts()];
}


reducers/PostsReducer.js

import { mapKeys } from 'lodash';
import { FETCH_POSTS } from '../actions';

export default (state = {}, action) => {
  switch (action.type) {
    case FETCH_POSTS:
    console.log(action);
      // Create a new state object that uses an AJAX request response and grabs the 'id' property from each object in the response to use as its key
      return mapKeys(action.payload.data, 'id');
  }

  return state;
};


似乎 reducer 仍在接收发出的 Action ,这是错误的。我确实注意到,如果我也在 Action 创建者中运行 AJAX 调用,那么 saga 将会运行,但传奇应该拦截 Action 创建者和 reducer 之间的通信,所以某些设置不太正确。有什么想法吗?

可以在 https://stackblitz.com/edit/react-redux-saga-demo 编辑我的工作流程的完整环境.在那里可能更容易看到问题。

最佳答案

Sagas 不会阻止 Action 到达 reducer 。 saga 中间件明确地做了等价于:

next(action); // pass the action onwards to the reducers
processSagas(action);

因此,reducers 总是先看到一个 Action ,然后再执行 saga 行为。

另一个问题是,看起来您正在尝试使用相同的操作类型来触发 saga 中的提取行为,在 reducer 中处理结果。我发现,如果您正在使用 sagas,您通常会有一些 Action 是“信号”,旨在触发 saga 行为,而其他 Action 则旨在由 reducer 实际处理并更新状态。因此,在您的情况下,我建议使用 "FETCH_POSTS" 作为开始获取的信号,然后让 saga 在收到数据后分派(dispatch) "FETCH_POSTS_SUCCESS"并让 reducer 响应该操作。 (而且,在注意到您已经启动了 StackBlitz 示例之后,我确认仅将结果分派(dispatch)为 "FETCH_POSTS_SUCCESS" 确实可以正常工作,正如我所期望的那样。)

关于javascript - 使用 React,为什么 redux saga 不拦截 Action ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46881778/

相关文章:

javascript - 将字符串替换为 JSX 标签

javascript - React Router 的 ES6 导入错误

reactjs - 在 React-Redux 应用程序中显示和管理错误消息的最佳实践

javascript - 我如何在 redux-saga 的回调中使用 yield?

react-native - redux saga 的延迟功能不起作用

javascript - Twitter Bootstrap Datepicker 错误

javascript - jQuery求div可以包含的字符串长度

javascript - 如何使用 React 滚动到 div onClick?

javascript - 带有斜杠分隔参数的 Ajax 请求

javascript - 计算结果与订单脚本不符