【问题标题】:Waiting for Ajax Call before Setting Initial State in React/Redux在 React/Redux 中设置初始状态之前等待 Ajax 调用
【发布时间】:2025-12-23 07:20:15
【问题描述】:

我正在使用 react 和 redux,想知道以下是否可行:

我正在制作一个“编辑表单”组件,我想将 preselected 的初始状态设置为 this.props.user.preselected.id。

除了设置初始值的情况外,我可以在任何地方调用this.props.user.preselected.id。我一直得到一个空值,我相信这是因为reducer this.props.user 仅在this.props.fetchSingleUser 完成后出现。

是否可以将初始状态设置为当前在同一组件中获取的 reducer?

class PropertyEdit extends Component {

  static contextTypes = {
    router: PropTypes.object
  };

  constructor(props) {
        super(props);
        this.state = { 
            preselected= this.props.user.preselected.id
        };       
  }


  componentWillMount() {
    this.props.fetchSingleUser(this.props.params.id);
  }

....


function mapStateToProps(state) {
  return { 
    user:state.user.single
  };
}


function mapStateToProps(state) {
  return { 
    user:state.users.single
  };
}

action.js

export function fetchSingleUser(id) {
  return function(dispatch) {
    axios.get(`${URL}/users/${id}`)
    .then(response => {
      dispatch({
        type:FETCH_USER,
        payload: response
      });
    })
   .catch(() => {
      console.log("Error ");
    });
  }
}

减速器:

const INITIAL_STATE = { single: null };

export default function(state = INITIAL_STATE, action) {
  switch (action.type) {
    case FETCH_USER:
        return {...state, single: action.payload.data};
  }
  return state;
}

【问题讨论】:

    标签: reactjs redux state


    【解决方案1】:

    非常常见的方法是为异步操作设置 3 个操作

    types.js

    export const FETCH_USER_REQUEST = 'FETCH_USER_REQUEST'
    export const FETCH_USER_SUCCESS = 'FETCH_USER_SUCCESS'
    export const FETCH_USER_FAIL = 'FETCH_USER_FAIL'
    

    reducer.js

    import {combineReducers} from 'redux';
    import * as types from './types';
    
    const isFetching = (state = false, action) => {
      switch (action.type) {
        case types.FETCH_USER_REQUEST:
          return true;
        case types.FETCH_USER_SUCCESS:
        case types.FETCH_USER_FAIL:
          return false;
        default:
          return state;
      }
    };
    
    const data = (state = {}, action) => {
      switch (action.type) {
        case types.FETCH_USER_SUCCESS:
          return action.payload.data;
      }
      return state;
    };
    
    export default combineReducers({
      isFetching,
      data
    });
    

    所以你可以在你的组件中获得isFetching prop 并显示/隐藏你的表单

    【讨论】:

      【解决方案2】:

      您不认为您应该只在收到用户数据后才呈现表单吗?

      • 使用 redux thunk,您可以在获取完成后发出操作 USER_LOADED
      • 这个新动作会用userLoaded = true更新redux store
      • 那么你可以在你的 react 组件中传递 user.loaded 来显示表单

      【讨论】:

      • 我刚刚添加到我的动作创建器中。我认为这是有道理的。您是说在获取用户并将其设置为要在组件中显示的减速器后我应该调度另一个操作吗?
      • 谢谢。看来您已经使用了 redux thunk。 this.props.usernull 是完全正常的,我会编辑我的帖子来解释一下