我试图在我的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"
},
答案 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
来绑定 mapStateToProps
和 mapDispatchToProps
。
出于某种原因,当我将 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
定义为对象。