Redux saga函数未被调用

时间:2018-05-07 12:07:49

标签: redux react-redux redux-saga

我试图在我的React项目中使用redux-saga,但是没有调用redux-saga函数。调用toggleLoginModal中的access.actions.js操作,但toggleLoginModal中的access.sagas.js未被调用。

Header.jsx

import React, { Component } from 'react';
import { withRouter } from 'react-router';
import accessActions from 'actions/access.actions';
import { connect } from 'react-redux';
import './Header.scss';

const { toggleLoginModal, toggleRegisterModal } = accessActions;

class Header extends Component {
  handleLoginClick = () => {
    toggleLoginModal(true);
  };

  render() {
    return (
        <div className="navbar-right">
            <button type="button" className="btn btn-link" onClick={this.handleLoginClick}>Log in</button>
            <button type="button" className="btn btn-primary">Register</button>
        </div>
    );
  }
}

export default withRouter(connect(null, { toggleLoginModal, toggleRegisterModal })(Header));

access.action.js

const actions = {
  TOGGLE_LOGIN_MODAL: 'TOGGLE_LOGIN_MODAL',
  TOGGLE_LOGIN_MODAL_RETURN: 'TOGGLE_LOGIN_MODAL_RETURN',
  toggleLoginModal: newState => ({
    type: actions.TOGGLE_LOGIN_MODAL,
    state: newState,
  }),
  toggleLoginModalReturn: (newState) => {
    return (dispatch) => {
      dispatch({
        type: actions.TOGGLE_LOGIN_MODAL_RETURN,
        newState,
      });
    };
  },
};
export default actions;

access.sagas.js

import { all, takeEvery, put } from 'redux-saga/effects';
import actions from 'actions/access.actions';

export function* toggleLoginModal({ state }) {
  yield put(actions.toggleLoginModalReturn(state));
}

export default function* rootSaga() {
  yield all([
    takeEvery(actions.TOGGLE_LOGIN_MODAL, toggleLoginModal),
  ]);
}

access.reducers.js

export function toggleModals(state = { login: false, register: false }, action) {
  switch (action.type) {
    case 'TOGGLE_LOGIN_MODAL_RETURN':
      return { login: action.newState };
    default:
      return state;
  }
}

reducers.js

import { toggleModals } from 'state/access.reducers.js';

export default {
  toggleModals,
};

sagas.js

import { all } from 'redux-saga/effects';
import accessSagas from 'sagas/access.sagas';

export default function* rootSaga() {
  yield all([accessSagas()]);
}

index.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import createHistory from 'history/createBrowserHistory';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { ConnectedRouter, routerReducer, routerMiddleware } from 'react-router-redux';
import { Provider } from 'react-redux';
import createSagaMiddleware from 'redux-saga';
import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly';

import App from 'App';
import reducers from 'reducers';
import sagas from 'sagas';

const history = createHistory();
const sagaMiddleware = createSagaMiddleware();

const store = createStore(
  combineReducers({
    ...reducers,
    router: routerReducer,
  }),
  composeWithDevTools(applyMiddleware(
    routerMiddleware(history),
    sagaMiddleware,
  )),
);

sagaMiddleware.run(sagas);

ReactDOM.render(
  <Provider store={store}>
    <ConnectedRouter history={history}>
      <App />
    </ConnectedRouter>
  </Provider>,
  document.getElementById('app'),
);

的package.json

"dependencies": {
    "bootstrap": "^4.1.1",
    "jquery": "^3.3.1",
    "js-cookie": "^2.2.0",
    "lodash": "^4.17.10",
    "moment": "^2.22.1",
    "popper.js": "^1.14.3",
    "react": "^16.3.2",
    "react-dom": "^16.3.2",
    "react-loadable": "^5.4.0",
    "react-modal": "^3.4.4",
    "react-redux": "^5.0.7",
    "react-router": "^4.2.0",
    "react-router-dom": "^4.2.2",
    "react-router-redux": "^5.0.0-alpha.9",
    "react-tippy": "^1.2.2",
    "react-toastify": "^4.0.1",
    "redux": "^4.0.0",
    "redux-saga": "^0.16.0"
  },

3 个答案:

答案 0 :(得分:1)

有两个问题。

首先,您需要使用道具中的toggleLoginModal - 因为它dispatch包含在connect中。引用https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-mapdispatchtoprops-mergeprops-options

  

[mapDispatchToProps(dispatch,[ownProps]):dispatchProps](对象或   功能):如果传递了一个对象,则假定其中的每个函数   成为Redux动作创作者。具有相同函数名的对象,   但是每个动作创建者都会被包裹在一个调度呼叫中,所以他们可以   直接调用,将​​合并到组件的道具中。

所以在Header.jsx中使用:

handleLoginClick = () => {
    this.props.toggleLoginModal(true);
};

第二个问题是你使用toggleLoginModalReturn作为thunk而没有thunk中间件。将redux-thunk添加到您的中间件列表中。

答案 1 :(得分:0)

只需将其留在这里,因为它可能会对某人有所帮助。在为项目配置sagas时遇到一个问题,即使所有内容都已正确配置和设置,传奇也不会触发。控制台也没有引发任何错误。但是实际的问题是,当定义状态的默认值(应该为对象提供默认值)时,我只是传递了null而不是使用属性构造整个对象(懒惰)。

因此,这实际上会导致错误,如果您尝试从这些对象访问属性,但将初始值传递为null,则将尝试从null访问属性-这会弄乱项目。在某些情况下,它会引发错误,而在某些情况下则不会。因此,这就是传奇故事也无法正常运行的原因。

答案 2 :(得分:0)

如果有人发现它有用,请删除它。 我使用 connect 中的 react-redux 来绑定 mapStateToPropsmapDispatchToProps

出于某种原因,当我将 mapDispatchToProps 用作函数时,分派的操作永远无法到达 saga 侦听器。我所要做的就是将变量从函数转移到一个简单的对象

来自

const mapDispatchToProps = (dispatch) => ({
  onChange: (settings) => saveUserSettings(settings),
  fetchDataOnMount: getUserSettings,
});

export default connect(mapStateToProps, mapDispatchToProps)(Settings);

到:

const mapStateToProps = (state) => ({
  userSettings: selectUserSettings(state),
  userSettingsStatus: selectUserSettingsStatus(state),
});

const mapDispatchToProps = {
  onChange: (settings) => saveUserSettings(settings),
  fetchDataOnMount: getUserSettings,
};

export default connect(mapStateToProps, mapDispatchToProps)(Settings);

当我的动作文件导出时:

export const getUserSettings = () => ({type: actions.FETCH_USER_SETTINGS});

export const saveUserSettings = (settings) => ({type: actions.SAVE_USER_SETTINGS, settings});

我意识到没有必要为 mapDispatchToProps 定义一个函数,因为我没有在函数上使用 dispatch 参数。此外,我返回的对象的每个字段都直接使用了动作创建者,在这种情况下,我们可以 Object Shorthand form where:

<块引用>

React-Redux 将你的 store 的 dispatch 绑定到每个 action 使用 bindActionCreators 的创建者。

Read more 关于将 mapDispatchToProps 定义为对象。