繁体   English   中英

React-Redux:在设置 state 后调用 api

[英]React-Redux: Make api call after set state

我有一个页面,可以在其中恢复有关某些经理的信息。 当用户使用<select>选择一个经理时,我将 ID 保存在 state 中。 现在我将使用这个 id 从另一个 api 进行另一个提取。

我的问题是,一开始经理 state 是未定义的,所以第二个 api 调用给我一个 500 错误,直到设置经理 ID。 一旦选择了管理器,就会连续调用 API(因为它已插入渲染中)。

在选择经理的 ID 后,我会找到一种方法来进行第二次 api 调用,您认为我该怎么做?

componentDidMount() {
// with this part I recover the managers' list
        this.props.managerList()
    }
//...
render() {
// this is the part:
         let managers = this.props.managers
         console.log("manager: ", managers)
         let idManager = this.state.manager_id; 
         console.log("idManager: ", idManager)
         if(typeof idManager != "undefined"){
          this.props.agendaList(idManager)
         }

        return (
      <div className = "ml-5 mr-5 mt-5">
          <div>
          </div>
        <form onSubmit={this.handleSubmit}>
         <div>
          <label>Manager</label>
          <div className="bootstrap-select-wrapper">
// there I save the manager_id that I pass in my second api (agendaList)
            <select title="Choose Option" onChange={(e) => this.setState({ manager_id: e.target.value })}>
            <option value="" title="Choose Option" data-content="Cancel <span class='reset-label'></span>"></option>
            {managers && managers.length && managers.map((manager) => (
              <option key={manager.id}  value= {manager.id}  name="manager_id" >{manager.name} {manager.surname}</option>
            ))}
            </select>
            </div>
          </div>

编辑。 好的,由于您的回答,我已经编辑了代码。 现在的问题是当我 select 经理并执行议程列表(manager_id)调用时,我得到:

在我选择经理之前:

(2) [{…}, {…}]

0: {id: "12", name: "Name1", surname: "Surname1"}
1: {id: "13", name: "Name2", surname: "Surname2"

之后(所以在我调用 this.props.agendaList(manager_id)

0: {id: "12", name: "Name1", surname: "Surname1"}
1: {id: "13", name: "Name2", surname: "Surname2"}
2: {manager_id: "12", date: "2020-05-27", start_at: "09:00:00"}
3: {manager_id: "12", date: "2020-05-27", start_at: "10:00:00"}

我换了经理

(5) [{…}, {…}, {…}, {…}, {…}]
0: {id: "12", name: "Name1", surname: "Surname1"}
1: {id: "13", name: "Name2", surname: "Surname2"}
2: {manager_id: "12", date: "2020-05-27", start_at: "09:00:00"}
3: {manager_id: "12", date: "2020-05-27", start_at: "10:00:00"}
4: {manager_id: "13", date: "2020-05-28", start_at: "10:00:00"}

我会将答案与我的 api 分开。

case 'MANAGER_LIST':
            return [...state, ...action.managers];
        case 'AGENDA_LIST':
            return [...state, ...action.agenda];

您不应该在渲染方法中进行任何 API 调用。 您可以编写一个单独的处理程序来设置 state 并进行 API 调用

handleChange = (e) => {
   const manager_id = e.target.value
   this.setState({ manager_id })
   this.props.agendaList(manager_id)
}
render() {
   let managers = this.props.managers
   console.log("manager: ", managers)
   let idManager = this.state.manager_id; 
   console.log("idManager: ", idManager)
   return (
      <div className = "ml-5 mr-5 mt-5">
         {/* Other code */>}
            <select title="Choose Option" onChange={this.handleChange}>
                <option value="" title="Choose Option" data-content="Cancel <span class='reset-label'></span>"></option>
                {managers && managers.length && managers.map((manager) => (
                  <option key={manager.id}  value= {manager.id}  name="manager_id" >{manager.name} {manager.surname}</option>
                ))}
            </select>
           {/*other code*/}
      </div>
   )
}

编辑:根据您编辑的帖子,您似乎希望数据是分开的。 为此,您需要将它们分别存储在减速器中

const reducer = (state = {managers: [], agents: []}, action) => {
     case 'MANAGER_LIST':
            return {...state, managers: [...state.managers, ...action.managers]};
        case 'AGENDA_LIST':
            return {...state, managers: [...state.managers, ...action.agenda]};
}

发布您也需要更新 mapStateToProps

const mapStateToProps = (state) => {
   return {
      managers: state.managers,
      agenda: state.agenda,
   }
}

您可以将第二个 api 调用包装在 if state 中,以便仅在管理器 state 未定义时执行。 并且您的 onChange 应该链接到外部渲染的 function ,这并不重要,但很好的做法。

不要在 state 中设置选定的 ID。 在 select 上,可以直接调用 redux 动作。 例如,

这将在经理下拉 select 上调用,

onMangerSelect(selectedId) {
    this.props.getManagerDetails(selectedId);
}

这将调用 redux 动作,

const mapDispatchToProps = dispatch => {
  return {
    getManagerDetails : (managerId) => {
      dispatch(getDataFromManagerAPI(managerId));
    } 
  };
};

好吧,React 是关于……反应性的。 使用 React 时,一个好的心态是始终对变化做出反应。

在我看来,可以像从组件中选择一个值时那样更改 state (*尽管我会写一个处理 function ,就像第一个答案一样,为了更清晰和更有条理的代码)。

您需要做的是确保有一段代码知道如何对该更改做出反应 -> 在我们的例子中,进行 API 调用。 一个示例解决方案可能是:

componentDidMount() {
// with this part I recover the managers' list
        this.props.managerList()
    }
componentDidUpdate(prevProps, prevState) {
        // Whenever the component updates we'll check what changed and react
        // accordingly
        this.handleNewManagerSelection(prevState);
    }
handleNewManagerSelection(prevState) {
        const { manager_id } = this.state;
        // This means we have a new manager id in our state so we need
        // to run our agendaList API call
        if (prevState.manager_id !== manager_id) {
                this.props.agendaList(manager_id);
            }
    }
render() {
// this is the part:
         let managers = this.props.managers
         console.log("manager: ", managers)
         let idManager = this.state.manager_id; 
         console.log("idManager: ", idManager)
         if(typeof idManager != "undefined"){
          this.props.agendaList(idManager)
         }

        return (
      <div className = "ml-5 mr-5 mt-5">
          <div>
          </div>
        <form onSubmit={this.handleSubmit}>
         <div>
          <label>Manager</label>
          <div className="bootstrap-select-wrapper">
// there I save the manager_id that I pass in my second api (agendaList)
            <select title="Choose Option" onChange={(e) => this.setState({ manager_id: e.target.value })}>
            <option value="" title="Choose Option" data-content="Cancel <span class='reset-label'></span>"></option>
            {managers && managers.length && managers.map((manager) => (
              <option key={manager.id}  value= {manager.id}  name="manager_id" >{manager.name} {manager.surname}</option>
            ))}
            </select>
            </div>
          </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM