2017-10-06 1 views
1

1つの非同期アクションクリエータ内に別のアクションをディスパッチしようとしています。しかし、私はredux-thunkミドルウェアによって提供されるディスパッチ機能を使用しているとき、それはUncaught TypeError: dispatch is not a functionエラーを投げています。以下は 非同期アクションクリエータ内でディスパッチが定義されていません

店/ 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; 

コンテナ/ 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; 

アクション/ 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; 

フォルダ構造

Project structure

私は非同期アクションクリエイターにディスパッチ機能を公開redux-thunkミドルウェアを使用しています。それでも動作しません。

助けてください!

+0

これはエラーの原因となっている行ですか? 'loginAction()();'私はあなたのコンポーネントにインポートするのではなく、 'mapDispatchToProps()'によって実装されたpropsから 'loginAction'を取得する必要があると思います。直接インポートすると、ラップされないので、 'dispatch()'はそれに渡されません。その行でない場合は、エラーの原因となっている行を教えてください!それはかなり重要な情報です。 – stone

+0

@skypecakes - 'actions/loginAction.js'の' dispatch(loginSubmitted()); 'はエラーを引き起こしています。 – Sourav

+0

これはloginAction()から呼び出されたものですか?そうであれば、あなたは明らかに 'ディスパッチ'を通過していないが、それはあなたに期待している。 – stone

答えて

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(); 
     }); 
} 

編集
あなたのコメントをフォローアップとして、最初のIAT私はあなたがミドルウェアとして適切redux-thunkを実装していませんが、あなたのコードによると、それはOKに見えると思いました。
それから、あなたは実際にloginActionを派遣しているわけではなく、それを呼び出すだけであることに気付きました。
dispatch(loginAction())を発送する必要があります。あなたのコンポーネントはreduxに接続する必要があります。dispatchにアクセスしてください。

+0

それは何の違いもありませんでした。私はディスパッチ引数を削除しても、それは同じエラーを投げている。 @ Sag1v – Sourav

+0

完全な例を見て、これはあなたのアクションクリエイターの様子ですか? –

+0

はい、全く同じです。私は行動から引数を削除しました – Sourav

関連する問題