未调用Redux saga函数

未调用Redux saga函数,redux,react-redux,redux-saga,Redux,React Redux,Redux Saga,我试图在React项目中使用redux saga,但没有调用redux saga函数toggleLoginModal操作,但未调用access.sagas.js中的toggleLoginModal Header.jsx import React, { Component } from 'react'; import { withRouter } from 'react-router'; import accessActions from 'actions/access.actions'; imp

我试图在React项目中使用redux saga,但没有调用redux saga函数<调用了
access.actions.js
中的code>toggleLoginModal操作,但未调用
access.sagas.js
中的
toggleLoginModal

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));
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'),
);
access.sagas.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;
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),
  ]);
}
export function toggleModals(state = { login: false, register: false }, action) {
  switch (action.type) {
    case 'TOGGLE_LOGIN_MODAL_RETURN':
      return { login: action.newState };
    default:
      return state;
  }
}
import { toggleModals } from 'state/access.reducers.js';

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

export default function* rootSaga() {
  yield all([accessSagas()]);
}
access.reducers.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;
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),
  ]);
}
export function toggleModals(state = { login: false, register: false }, action) {
  switch (action.type) {
    case 'TOGGLE_LOGIN_MODAL_RETURN':
      return { login: action.newState };
    default:
      return state;
  }
}
import { toggleModals } from 'state/access.reducers.js';

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

export default function* rootSaga() {
  yield all([accessSagas()]);
}
reducers.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;
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),
  ]);
}
export function toggleModals(state = { login: false, register: false }, action) {
  switch (action.type) {
    case 'TOGGLE_LOGIN_MODAL_RETURN':
      return { login: action.newState };
    default:
      return state;
  }
}
import { toggleModals } from 'state/access.reducers.js';

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

export default function* rootSaga() {
  yield all([accessSagas()]);
}
sagas.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;
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),
  ]);
}
export function toggleModals(state = { login: false, register: false }, action) {
  switch (action.type) {
    case 'TOGGLE_LOGIN_MODAL_RETURN':
      return { login: action.newState };
    default:
      return state;
  }
}
import { toggleModals } from 'state/access.reducers.js';

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

export default function* rootSaga() {
  yield all([accessSagas()]);
}
index.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));
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'),
);

有两个问题

首先,您需要使用props中的
toggleLoginModal
,因为它包装在
dispatch
中,这要归功于
connect
。举出

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

因此,在Header.jsx中使用:

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

第二个问题是,在没有thunk中间件的情况下,将
toggleLoginModelReturn
用作thunk。将
redux thunk
添加到您的中间产品列表中。

只需将此留在此处,因为它可能会帮助某些人。我在为一个项目配置saga时遇到了一个问题,在这个项目中,即使所有的配置和设置都恰到好处,也不会触发saga。控制台也没有抛出任何错误。但实际的问题是,在为状态定义默认值时,我应该为对象提供默认值,我只是传递null,而不是用属性构造整个对象(lazy me)


因此,这实际上会导致错误,如果您试图从这些对象访问属性,但将初始值传递为null,那么您将尝试从null访问属性,这将使项目陷入混乱。在某些情况下,它会抛出错误,而在某些情况下则不会。因此,这也是这部传奇故事不能正常运作的原因。

如果有人发现它有用,就放弃它。 我使用
connect
from
react redux
绑定
mapstatetrops
mapsdispatchtoprops

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

致:

导出操作文件时:

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

export const saveUserSettings = (settings) => ({type: actions.SAVE_USER_SETTINGS, settings});
我意识到没有必要为mapDispatchToProps定义函数,因为我没有在函数上使用dispatch参数。此外,我返回对象的每个字段都直接使用动作创建者,在这种情况下,我们可以在以下位置:

React-Redux将存储的分派绑定到每个操作 使用bindActionCreators的创建者


关于将
mapDispatchToProps
定义为对象。

感谢您的回复。我试着跟随这个项目,那里有类似的代码。如果我试一下你的例子,我会在rootSaga处发现
未捕获错误:fork:argument[object Generator]不是函数
Error你确定使用了
fork(accessSagas)
而不是
fork(accessSagas())
<代码>[object Generator]是你一旦称之为传奇故事就会得到的。你是对的,我很抱歉我的错误。我试过了,但没什么变化,
access.sagas.js
中的
toggleLoginModal
没有被调用。但是,调用了action
toggleLoginModal
。对,所以我仔细查看了您的代码,找到了问题的实际原因。请看我的最新答案。谢谢,现在它可以工作了。在该示例中,如何可能不从
道具触发项目操作?例如,这里的函数。