You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React新手求助:如何在Redux Action中处理状态并传递错误信息

Fixing Redux Action & Error Handling Issues in Your React App

Hey there! Let's walk through the issues in your code and fix them properly—since you're using Redux (with redux-promise-middleware), state and error handling work differently than plain React, so we'll align your code with Redux best practices.

Key Issues in Your Current Code

  • You can't call this.setState inside a Redux Action: Actions are meant to describe what happened, not directly modify component state. Plus, this in your action isn't referencing your Layout component at all—so self.setState will throw an error.
  • Passing this.state.errors to the action is unnecessary: Errors should be captured by Redux (via the reducer) and then passed back to your component through props, not the other way around.
  • Redux-promise-middleware handles promise resolution/rejection for you: You don't need manual .then()/.catch() in your action, because the middleware automatically dispatches _PENDING, _FULFILLED, and _REJECTED actions based on the promise's outcome.

1. Updated src/actions/userActions.js

We'll remove manual promise handlers and let the middleware do its job:

import axios from 'axios';

// Replace with your actual API endpoint
const API_URL = 'https://your-api-url.com/users';

export function postUsers(username, password) {
  const userData = { username, password };
  
  return {
    type: "USERS_POST",
    payload: axios({
      method: 'POST',
      url: API_URL,
      data: userData,
      headers: {
        'Accept': 'application/json',
        'Content-Type': 'application/json',
      }
    })
  };
}

2. Updated src/components/layout.js

We'll remove the local errors state, fetch errors from the Redux store via props, fix the input name typo, and clean up the action call:

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { postUsers } from '../actions/usersAction';

class Layout extends Component {
  constructor(props) {
    super(props);
    this.state = {
      username: '',
      password: '',
      // Removed local errors state—we'll use Redux store's error instead
    };
  }

  onUserUpdate(field, event) {
    this.setState({ [field]: event.target.value });
  }

  handlePostUsers(e) {
    e.preventDefault();
    // No need to pass errors—action handles fetching, reducer handles error storage
    this.props.postUsers(this.state.username, this.state.password);
  }

  render() {
    // Get error state from Redux props
    const { error, fetching } = this.props.act;
    
    return (
      <div className="App">
        <input 
          name="username" 
          onChange={this.onUserUpdate.bind(this, 'username')}
          value={this.state.username}
          placeholder="Username"
          disabled={fetching}
        />
        {/* Fixed input name from "username" to "password" */}
        <input 
          name="password" 
          type="password"
          onChange={this.onUserUpdate.bind(this, 'password')}
          value={this.state.password}
          placeholder="Password"
          disabled={fetching}
        />
        <button 
          onClick={(e) => this.handlePostUsers(e)}
          disabled={fetching}
        >
          {fetching ? 'Submitting...' : 'Go ahead'}
        </button>
        
        {/* Display errors if they exist */}
        {error.length > 0 && (
          <div style={{ color: 'red', marginTop: '1rem' }}>
            {error.map((err, index) => (
              <p key={index}>{err}</p>
            ))}
          </div>
        )}
      </div>
    );
  }
}

function mapStateToProps(state) {
  return {
    act: state.users,
  };
}

function matchDispatchToProps(dispatch) {
  return bindActionCreators({ postUsers }, dispatch);
}

export default connect(mapStateToProps, matchDispatchToProps)(Layout);

3. Minor Adjustment to src/reducers/userReducers.js

Your reducer is mostly correct—we'll ensure we're accessing the right data from axios responses:

const initialState = {
  fetching: false,
  fetched: false,
  users: [],
  error: []
};

export default function(state = initialState, action) {
  switch(action.type) {
    case "USERS_POST_PENDING": {
      return {...state, fetching: true};
    }
    case "USERS_POST_FULFILLED": {
      return {
        ...state, 
        fetching: false,
        fetched: true, 
        users: [...state.users, action.payload.data] // Axios wraps responses in .data
      };
    }
    case "USERS_POST_REJECTED": {
      return {
        ...state, 
        fetching: false, 
        error: action.payload.response.data // Capture error details from the API
      };
    }
    default:
      return state;
  }
}

4. Fix src/index.js

You had an undefined loadingBarMiddleware() call—remove it or import it if you intend to use it:

import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, applyMiddleware } from 'redux'
import thunk from 'redux-thunk';
import logger from 'redux-logger';
import promise from 'redux-promise-middleware';
import reducers from './reducers/index';
import { Provider } from 'react-redux';
import registerServiceWorker from './registerServiceWorker';
import Layout from './components/layout';

// Removed undefined loadingBarMiddleware
const store = createStore(reducers, applyMiddleware(promise(), thunk, logger));

const app = document.getElementById('root');
ReactDOM.render(
  <Provider store={store}>
    <Layout />
  </Provider>,
  app
);
registerServiceWorker();

How This Works Now

  1. When you click the "Go ahead" button, postUsers is dispatched with your username/password.
  2. Redux-promise-middleware immediately dispatches USERS_POST_PENDING, which sets fetching: true in your store (we use this to disable inputs/button during loading).
  3. If the API call succeeds: middleware dispatches USERS_POST_FULFILLED, which adds the new user to your store and marks fetching: false.
  4. If the API call fails: middleware dispatches USERS_POST_REJECTED, which stores the error data in your store.
  5. Your Layout component receives the error from the store via props, and displays it automatically when it exists.

内容的提问来源于stack exchange,提问作者Liam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 08:40:47