Reactjs React/Redux调度未触发减速器

Reactjs React/Redux调度未触发减速器,reactjs,redux,react-redux,Reactjs,Redux,React Redux,正在努力从我的React组件发送操作。这是我的第一个Redux应用程序。一切似乎都很好,但如果是这样,我就不会发布这个问题。我正在使用Redux devTool调试我的应用程序。如果我使用devTools中的dispatcher,我的减速器将毫无问题地触发。但是,我无法从我的React组件发送相同的操作。我在我的操作中添加了一个断点,以查看它是否被触发。我肯定是,它也返回了一个有效的操作(类型和负载)。这是我的密码: store.js import {createStore, applyMidd

正在努力从我的React组件发送操作。这是我的第一个Redux应用程序。一切似乎都很好,但如果是这样,我就不会发布这个问题。我正在使用Redux devTool调试我的应用程序。如果我使用devTools中的dispatcher,我的减速器将毫无问题地触发。但是,我无法从我的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
import {combineReducers} from 'redux'
import userReducer from './userReducer'

const allReducers = combineReducers({
    user: userReducer
})

export default allReducers
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')
);
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;
}
export const login = () => {
  console.log("TEST")
    return {
        type: 'LOGIN',
        payload: true
    }
}
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
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)
减速器(index.js)

client.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
import {combineReducers} from 'redux'
import userReducer from './userReducer'

const allReducers = combineReducers({
    user: userReducer
})

export default allReducers
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')
);
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;
}
export const login = () => {
  console.log("TEST")
    return {
        type: 'LOGIN',
        payload: true
    }
}
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
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)
userActions.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
import {combineReducers} from 'redux'
import userReducer from './userReducer'

const allReducers = combineReducers({
    user: userReducer
})

export default allReducers
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')
);
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;
}
export const login = () => {
  console.log("TEST")
    return {
        type: 'LOGIN',
        payload: true
    }
}
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
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)
login.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
import {combineReducers} from 'redux'
import userReducer from './userReducer'

const allReducers = combineReducers({
    user: userReducer
})

export default allReducers
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')
);
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;
}
export const login = () => {
  console.log("TEST")
    return {
        type: 'LOGIN',
        payload: true
    }
}
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
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)
从“React”导入React
从“react dom”导入react dom
从“../containers/LoginForm”导入LoginForm
类登录扩展了React.Component{
render(){
返回(
)
}
}
导出默认登录名
loginform.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
import {combineReducers} from 'redux'
import userReducer from './userReducer'

const allReducers = combineReducers({
    user: userReducer
})

export default allReducers
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')
);
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;
}
export const login = () => {
  console.log("TEST")
    return {
        type: 'LOGIN',
        payload: true
    }
}
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
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)
import React,{PropTypes}来自“React”
从“react dom”导入react dom
从“react router dom”导入{Redirect}
从“react redux”导入{connect}
从“../actions/userActions”导入{login}
从“物料ui/RaisedButton”导入RaisedButton
从“物料界面/文本字段”导入文本字段
类LoginForm扩展了React.Component{
建造师(道具){
超级(道具)
}
后勤(e){
e、 预防默认值()
this.props.login()
}
render(){
返回(
)
}
}
常量mapStateToProps=(状态)=>{
返回{
loggedIn:state.user.loggedIn
}
}
const mapDispatchToProps=(调度)=>{
返回{
登录:()=>分派(登录())
}
}
导出默认连接(MapStateTrops、mapDispatchToProps)(LoginForm)
请您给我一些指导,告诉我如何调试以找出此调度不起作用的原因。我已经尝试将action对象直接添加到分派函数中。还是不走运。我在控制台中没有收到任何错误。仅当视图呈现和单击“登录提交”按钮时,才会打印My console.log


我的直觉是,您将如何尝试调用函数来分派操作。首先,将函数绑定到组件构造函数中的
this
(有关更多信息,请参阅事件处理程序上的React文档)。第二,只需将函数传递给submit

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

终于发现了我的问题。我的中间件实现导致了这个问题。我传递的
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开发工具来说,它更干净。

修改操作:

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

我想您会喜欢=>这种情况下的语法。

您检查过控制台中是否有一些错误吗?您的代码似乎是正确的。我不确定这是否与您的调度问题有关,但您的
createStore
调用中似乎有错误。Redux DevTools扩展增强器应该是
compose()
调用的一部分,在
applyMiddleware()
之后。另一个建议是:虽然
mapDispatch
的用法看起来是正确的,只是为了好玩,请尝试使用另一种方式绑定操作创建者:
导出默认连接(MapStateTrops,{login})(LoginForm)
。如果这不起作用,我建议访问Discord上的Reactiflux聊天频道并寻求帮助。邀请链接位于。嘿,Michael,谢谢你的知识分享。不幸的是,它仍然不起作用。这应该很简单。开始有点沮丧了。我看了很多视频,似乎我的实现应该可以工作。我甚至尝试在分派功能中硬编码该操作,但它仍然没有触发我的减速机。我不知道如何调试从我的动作到我的减缩器的连接,因为我的动作函数肯定会被触发。你的事件处理程序在链的每个阶段都会被调用吗?有例外吗?如果你有一个调试器,那么从点击按钮到点击减速机的每一步都要中断。如果调试器失败,请在您认为代码应该达到的每个阶段都使用老式的console.log。我不熟悉Redux Dec工具的扩展,但我也倾向于将您的商店创建恢复到基础和构建。您是否能够做一个小型的独立的裸体Redux示例来确保它能够以这种方式工作?