【问题标题】:dispatch is not defined inside async action creators调度未在异步操作创建者内部定义
【发布时间】:2018-03-18 01:08:01
【问题描述】:

我正在尝试在一个异步操作创建器中调度另一个操作。但是,当我使用 redux-thunk 中间件提供的调度功能时,它会抛出 Uncaught TypeError: dispatch is not a function 错误。

以下是更多帮助文件

store/store.dev.js

use strict';

import { createStore, applyMiddleware } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import rootReducer from '../reducers';
import ReduxThunk from 'redux-thunk';

export default function configureStore(initialState = {}) {
const store = createStore(rootReducer, initialState, applyMiddleware(ReduxThunk));
  console.log('store returned', store);
return store;
}

src/index.js

'use strict';

import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { hydrate } from 'react-dom';
import { Provider } from 'react-redux';
import { renderRoutes } from 'react-router-config';
import configureStore from './store';
import App from './containers/App.js';
import routes from './routes/index.js';

hydrate(
  <Provider store={configureStore()}>
    <BrowserRouter>
      {renderRoutes(routes)}
    </BrowserRouter>
  </Provider>,
  document.getElementById('root')
);

减速器

'use strict';

import { LOGIN_SUBMITTED, LOGIN_COMPLETED } from '../constants/ActionTypes.js';

const loginSubmitReducer = (state = [], action) => {
  console.log('in reducer');
    switch (action.type) {

      case LOGIN_SUBMITTED:
      console.log('login submitted case');
        return Object.assign({}, state, {
          loginSubmitted: true
        });

      case LOGIN_COMPLETED:
      console.log('login completed case');
        return Object.assign({}, state, {
          loginCompleted: true
        });

      default:
      console.log('in default case');
        return {
          a:1
        };
    }
}

export default loginSubmitReducer;

containers/App.js

'use strict';

import React from 'react';
import { loginCompleted, loginSubmitted } from '../actions';
import { createStructuredSelector, createSelector } from 'reselect';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { Header, ButtonDemo, LoginForm } from '../components';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import lightBaseTheme from 'material-ui/styles/baseThemes/lightBaseTheme';
import getMuiTheme from 'material-ui/styles/getMuiTheme';

class App extends React.Component {
  constructor(props, context) {
    super(props);
    this.state = {
      appState: {
        entry: 'yes'
      }
    }

    console.log('props in App constructor', props);
    console.log('context in App constructor', context);

    this.newFunc = this.newFunc.bind(this);
  }
  newFunc () {
    console.log('props', this.props);
  }
  render() {
    console.log('props in main App', this.props);
    console.log('Actions', this.props.actions);
    console.log('context in App', this.context);
    // this.props.actions.loginCompleted();
    const muiTheme = getMuiTheme({
      lightBaseTheme
    });

    return (
      <MuiThemeProvider muiTheme={muiTheme}>
        <div>
            <Header />
            <LoginForm 
              appstate = {this.props.appState}
              dispatchAction = {this.props.actions}
            />
        </div>
      </MuiThemeProvider>
    );
  }
}

// const mapStateToProps = createStructuredSelector({});
const mapStateToProps = (state) => {
  return { appState: state.loginSubmitReducer };
}

function mapDispatchToProps(dispatch) {
  return {
    actions: bindActionCreators({ loginCompleted, loginSubmitted }, dispatch)
  };
  // dispatch(loginCompleted());
}

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

组件

    'use strict';

import React, { PropTypes } from 'react';
import TextField from 'material-ui/TextField';
import RaisedButton from 'material-ui/RaisedButton';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import ContentAdd from 'material-ui/svg-icons/content/add';
import { loginAction } from '../actions';
// import '../css/style.css';


class LoginForm extends React.Component {
    constructor(props) {
        super(props);
        this.loginSubmit = this.loginSubmit.bind(this);
    }

    loginSubmit() {
        console.log('Login fomr submitted', this.props);
        console.log('loginAction', loginAction);
        loginAction()();
    }

    render () {
        console.log('props when login rendered', this.props);
        return (
            <div className="loginForm">
                <div className="title">LOGIN</div>
                <form>
                    <TextField 
                        hintText="Username"
                        floatingLabelText="Username"/><br/>
                    <br/>
                    <TextField
                        hintText="Password"
                        type="Password"
                        floatingLabelText="Password"/><br/>
                    <br/>
                    <RaisedButton
                        label="Login" 
                        secondary={true} 
                        onClick={this.loginSubmit}
                        className="submitBtn" /><br/>
                    <br/>
                    <FloatingActionButton                       
                        secondary={true}
                        className="registerBtn">
                        <ContentAdd />                      
                    </FloatingActionButton>
                </form>
            </div>
        )
    }
}

export default LoginForm;

actions/loginAction.js

'use strict';

// import { polyfill } from 'es6-promise';
// require('es6-promise').polyfill();
// require('isomorphic-fetch');
import request from 'superagent';
// import fetch from 'isomorphic-fetch';
import loginCompleted from './loginCompletedAction.js';
import loginSubmitted from './loginSubmittedAction.js';

const loginAction = (dispatch) => {
    console.log('validateUserLogin executed', this);
    console.log('validateUserLogin dispatch', dispatch);
    return (dispatch) => {
        // console.log('first return', dispatch);
        // this.props.dispatch(loginSubmitted());
        // this.props.dispatchAction.loginSubmitted();
        dispatch(loginSubmitted());

        request.get('http://localhost:3000/loginSubmit')
            .end((err, res) => {
                console.log('res', res);
                console.log('err', err);
                // this.props.dispatchAction.loginCompleted();
            });
    }
}

export default loginAction;

文件夹结构

我正在使用redux-thunk 中间件,它向异步操作创建者公开调度功能。还是不行。

请帮忙!

【问题讨论】:

  • 这是导致错误的行吗? loginAction()(); 我认为你需要从 props 中获取loginAction (由mapDispatchToProps()) 填充,而不是在你的组件中导入它。当你直接导入它时,它不会被包装,所以dispatch() 不会传入它. 如果不是那一行,请告诉我们是哪一行导致了错误!这是非常重要的信息。
  • @skypecakes -- dispatch(loginSubmitted()); in actions/loginAction.js 导致错误。
  • 好的,但是是从 loginAction() 调用的吗?如果是,你显然没有传入dispatch,但它希望你这样做。
  • @skypecakes--是的..我没有通过。让我检查一下。
  • loginAction 如果您 dispatch(loginAction()) 将起作用,并进行 @Sag1v 建议的更改。通常的方法是在mapDispatchToProps。否则dispatch 将不会被定义。您可能会发现研究 dispatch 的传递方式会有所帮助 - 所有箭头功能似乎都很神秘(嗯,对我来说确实如此),但有一条清晰的路径。

标签: javascript node.js reactjs redux redux-thunk


【解决方案1】:

动作创建者的第一个参数不应该是dispatch,而是传递给动作创建者的参数。

const loginAction = () => (dispatch) => {
    console.log('validateUserLogin executed', this);
    console.log('validateUserLogin dispatch', dispatch);
    // console.log('first return', dispatch);
    // this.props.dispatch(loginSubmitted());
    // this.props.dispatchAction.loginSubmitted();
    dispatch(loginSubmitted());

    request.get('http://localhost:3000/loginSubmit')
        .end((err, res) => {
            console.log('res', res);
            console.log('err', err);
            // this.props.dispatchAction.loginCompleted();
        });
}

编辑
作为您评论的后续行动,我起初认为您没有将redux-thunk 作为中间件正确实施,但根据您的代码,它看起来不错。
然后我注意到您并没有真正调度loginAction,而只是调用它。
您应该发送它dispatch(loginAction())。你的组件应该连接到redux,然后你就可以访问dispatch

【讨论】:

  • 那没有任何区别。我已经删除了 dispatch 参数,但它仍然抛出同样的错误。 @Sag1v
  • 看完整的例子,这就是你的动作创建者的样子吗?
  • 是的,完全一样。我从行动中删除了论点
猜你喜欢
  • 1970-01-01
  • 2018-11-23
  • 1970-01-01
  • 2018-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-01
  • 1970-01-01
相关资源
最近更新 更多