React / Redux调度不会触发reducer

时间:2017-05-18 14:51:41

标签: reactjs redux react-redux

努力从我的React组件调度一个动作。这是我的第一个Redux应用程序。一切似乎都运转良好,但如果是,我不会发布这个问题。我正在使用Redux devTool来调试我的应用程序。如果我使用devTools中的调度程序,我的减速器会被触发,没有任何问题。但是,我无法从我的React组件中调度相同的操作。我在动作中添加了一个断点,看它是否被触发。我肯定是,它也返回一个有效的动作(类型和有效载荷)。这是我的代码:

store.js

import {createStore, applyMiddleware, compose} from 'redux'
import {createLogger} from 'redux-logger'
import thunk from 'redux-thunk'
import promise from 'redux-promise-middleware'
import reducers from './reducers/index'

const logger = createLogger()

const store = createStore(
    reducers,
    window.__REDUX_DEVTOOLS_EXTENSION__ && 
    window.__REDUX_DEVTOOLS_EXTENSION__(),
    compose(
      applyMiddleware(thunk, promise, logger)
    )
)

export default store

redurs(index.js)

import {combineReducers} from 'redux'
import userReducer from './userReducer'

const allReducers = combineReducers({
    user: userReducer
})

export default allReducers

client.js

import React from 'react'
import ReactDOM from 'react-dom'
import {Provider} from 'react-redux'
import store from './store'
import Router from './modules/router'
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'
import getMuiTheme from 'material-ui/styles/getMuiTheme'
import CustomTheme from './modules/theme'
import injectTapEventPlugin from 'react-tap-event-plugin'
require('../scss/style.scss')

// Needed for onTouchTap
// http://stackoverflow.com/a/34015469/988941
injectTapEventPlugin();

ReactDOM.render(
  <Provider store={store}>
    <MuiThemeProvider muiTheme={CustomTheme}>
      <Router/>
    </MuiThemeProvider>
  </Provider>,
  document.getElementById('app')
);

userReducer.js

export default function (state = {loggedIn: false}, action) {
    console.log("THIS IS THE REDUCER: STATE: ", state, " - ACTION: ", action)
    switch (action.type) {
        case 'LOGIN':
            return {...state, loggedIn: action.payload}
    }
    return state;
}

userActions.js

export const login = () => {
  console.log("TEST")
    return {
        type: 'LOGIN',
        payload: true
    }
}

login.js

import React from 'react'
import ReactDOM from 'react-dom'
import LoginForm from '../containers/loginform'

class Login extends React.Component {
  render() {
    return (
      <LoginForm/>
    )
  }
}

export default Login

loginform.js

import React, {PropTypes} from 'react'
import ReactDOM from 'react-dom'
import {Redirect} from 'react-router-dom'
import {connect} from 'react-redux'
import {login} from '../actions/userActions'
import RaisedButton from 'material-ui/RaisedButton'
import TextField from 'material-ui/TextField'

class LoginForm extends React.Component {
  constructor(props) {
    super(props)
  }
  loginReq(e){
     e.preventDefault()
     this.props.login()
  }
  render() {
    return (
      <div>
        <form className='login-form-container' onSubmit=    {this.loginReq.bind(this)}>
          <div className='login-form-row'>
            <TextField
              ref='email'
              hintText='Email'
              floatingLabelText='Email'
              className='login-form-field'/>
          </div>
          <div className='login-form-row'>
            <TextField
              ref='password'
              hintText='Password'
              floatingLabelText='Password'
              type='password'
              className='login-form-field'/>
          </div>
          <div className='login-form-row'>
            <RaisedButton
              type= 'submit'
              label='Login'
              className='login-form-button'/>
          </div>
        </form>
      </div>
    )
  }
}

const mapStateToProps = (state) => {
    return {
        loggedIn: state.user.loggedIn
    }
}

const mapDispatchToProps = (dispatch) => {
    return {
      login: () => dispatch(login())
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(LoginForm)

请你能给我一些指导,告诉我如何进行调试,找出为什么这个调度不起作用。我已经尝试将动作对象直接添加到该调度函数中。仍然没有运气。我在控制台中没有任何错误。我的console.logs仅在视图呈现时以及单击登录提交按钮时打印。

Console Screenshot

3 个答案:

答案 0 :(得分:6)

终于找到了我的问题。我的中间件实现导致了这个问题。我错误地传递了promise。应该是:

import {createStore, applyMiddleware} from 'redux'
import {composeWithDevTools} from 'redux-devtools-extension'
import {createLogger} from 'redux-logger'
import thunk from 'redux-thunk'
import promise from 'redux-promise-middleware'
import reducers from './reducers/index'

const logger = createLogger()

const middleware = applyMiddleware(promise(), logger, thunk)

const store = createStore(reducers, composeWithDevTools(middleware))

export default store

还发现redux-devtools-extension对于Redux devTools来说更清晰。

答案 1 :(得分:1)

我的预感就是你试图调用函数来调度动作。首先,将函数绑定到组件构造函数中的this(有关更多信息,请参阅事件处理程序here上的React文档)。其次,只需将函数传递给onSubmit

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

  loginReq(e) {
    e.preventDefault()
    this.props.login()
  }

  render() {
    return (
      <div>
        <form className='login-form-container' onSubmit={this.loginReq}>
          <div className='login-form-row'>
            <TextField
              ref='email'
              hintText='Email'
              floatingLabelText='Email'
              className='login-form-field'/>
          </div>
          <div className='login-form-row'>
            <TextField
              ref='password'
              hintText='Password'
              floatingLabelText='Password'
              type='password'
              className='login-form-field'/>
          </div>
          <div className='login-form-row'>
            <RaisedButton
              type= 'submit'
              label='Login'
              className='login-form-button'/>
          </div>
        </form>
      </div>
    )
  }
}

将函数绑定到this的另一种方法是删除构造函数中的bind语句,并使用箭头函数作为表单prop,如下所示:

onSubmit={e => this.loginReq(e)}

答案 2 :(得分:0)

修改行动:

export const login = () => {
  return function (dispatch) {
    console.log('here');
    dispatch({
        type: 'LOGIN',
        payload: true
    });
  }
}

我想你喜欢=&gt;在这种情况下的语法。