未调用Redux saga函数
我试图在React项目中使用redux saga,但没有调用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
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
fromreact 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
没有被调用。但是,调用了actiontoggleLoginModal
。对,所以我仔细查看了您的代码,找到了问题的实际原因。请看我的最新答案。谢谢,现在它可以工作了。在该示例中,如何可能不从道具触发项目操作?例如,这里的函数。