2017-10-06 5 views
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; 

폴더 구조 내가 비동기 액션 제작자로 파견 기능을 노출 redux-thunk 미들웨어를 사용하고

Project structure

. 여전히 작동하지 않습니다.

도와주세요!

+0

오류의 원인이되는 부분입니까? 'loginAction()();'나는 여러분의 컴포넌트에서 import하는 대신에'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(); 
     }); 
} 

편집
첫 번째 난 당신이 중간 도자기로 제대로 redux-thunk을 구현하는 것이 아니라 코드에 따라이 좋아 보인다 생각 IAT, 당신의 의견을 후속.
그럼 실제로 당신이 loginAction을 파견하지 않고 방금 호출하고있는 것으로 나타났습니다.
dispatch(loginAction())을 발송해야합니다. 구성 요소는 redux에 연결되어야하며 dispatch에 액세스 할 수 있습니다.

+0

아무런 차이가 없었습니다. 디스패치 인수를 제거했지만 여전히 동일한 오류가 발생합니다. @ Sag1v – Sourav

+0

전체 예제를 보니,이게 당신의 행동 창작자가 어떻게 생겼습니까? –

+0

예, 정확히 동일합니다. 내가 조치에서 인수를 제거했습니다 – Sourav