在React中的点击处理程序中解决访问承诺

时间:2019-05-31 02:29:43

标签: javascript reactjs promise async-await es6-promise

此用例包含三个步骤:
1.进行API调用以检查记录是否存在
2.如果记录存在,请询问用户是否要将其添加到组中
3.如果用户在我们要求他们的显示模式上单击“确定”,则继续另一个网络请求。

我正在尝试使用在自定义组件中编写的模式确认来获取用户输入,并基于用户单击确定或取消的事实,我想发出网络请求。

即使将其分配给“ onClick”处理程序可以访问的变量,我也无法访问promise resolve函数。

我已经尝试在用户单击的按钮的onClick处理程序中访问promise resolve函数。原来是不确定的。

getUserResponse作为参数发送到另一个函数中,该函数存在于单独的JS文件中,在该文件中进行了所有网络调用。在发现记录因API调用而存在之后被调用在那里

let outsideResolve;
const getUserResponse = async () => {
    return await new Promise((resolve, reject) => {
      outsideResolve = resolve;
    });
  };

const confirmAddRecord = event => {
    event.preventDefault();
    //resolve the promise after the button click
    outsideResolve(); //error: outsideResolve is not a function
    };

return (
      <div>
        <p>Record Exists would you like to add them to the group?</p>
        <button onClick={confirmAddRecord}>Add Existing record !</button>
      </div>
    );


*********************************
in another file (networkCalls.js), getUserResponse is sent 
as an argument to a method called in the file summarized above
try {
    let userResponse = await getUserResponse();
    console.log(userResponse);
    //Do more stuff after the reply comes in
  } catch (error) {
    console.log(error);
  }

我创建了一个codeSandbox来重新创建该问题的详细信息: https://codesandbox.io/s/promisemodal-tke67

2 个答案:

答案 0 :(得分:0)

如果我对您的理解正确-您遇到的主要问题是可以从原始(check if user exists)API调用中访问信息。根据该return版信息,您想采取其他措施。

请查看我对您的问题的解决方案(已在您的codesandbox上进行了测试)。这是实现(https://codesandbox.io/s/promisemodal-z2r5i)的分支

index.js下方

import React, { useState } from "react";
import ReactDOM from "react-dom";

import {
  ADD_NEW_RECORD,
  MAKE_API_CALL_AFTER_RECORD_CHECK
} from "./networkCalls";

import "./styles.css";

function App() {
  const [isModalOpen, setIsModelOpen] = useState(false);
  const [infoFromCreateRecord, setInfoFromCreateRecord] = useState({});

  const createRecord = () => {
    ADD_NEW_RECORD(isModalOpen, setIsModelOpen, setInfoFromCreateRecord);
  };

  const confirmAddRecord = () => {
    MAKE_API_CALL_AFTER_RECORD_CHECK(infoFromCreateRecord);
    setIsModelOpen(false);
  };

  const renderModal = () => {
    return (
      <div>
        <p>Record Exists would you like to add them to the group?</p>
        <button onClick={confirmAddRecord}>Add Existing record !</button>
      </div>
    );
  };

  return (
    <div className="App">
      <p>Add record by pressing this button</p>
      <button onClick={createRecord}>Create record </button>
      {isModalOpen ? renderModal() : ""}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

networkCalls.js下方

export const ADD_NEW_RECORD = (
  isModalOpen,
  setIsModalOpen,
  setInfoFromCreateRecord
) => {
  //checking from an API of record exists

  const checkIfRecordExists = new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("Record Exists");
      resolve("Record Exists");
    }, 1000);
  });

  //record exists, ask the user if they want to add them to the group
  checkIfRecordExists.then(() => {
    setInfoFromCreateRecord({
      importantInfo: "record does exits"
    });
    setIsModalOpen(!isModalOpen);
  });
};

export const MAKE_API_CALL_AFTER_RECORD_CHECK = infoFromCreateRecord => {
  // do some stuff with the info from the first API call

  const doSomethingAfterRecordCheck = new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log(infoFromCreateRecord);
      resolve("User got added to the group!");
    }, 1000);
  });

  doSomethingAfterRecordCheck.then(() => {
    console.log("do something after adding the user to the group");
  });
};

答案 1 :(得分:0)

我觉得network.js应该只返回promise,而这些promise应该在您的主要组件中解决

import React, { useState } from "react";
import ReactDOM from "react-dom";

import { ADD_NEW_RECORD } from "./networkCalls";

import "./styles.css";

function App() {
  const [isModalOpen, setIsModelOpen] = useState(false);

  let createRecordPromsie = null;
  const createRecord = () => {
    createRecordPromsie = ADD_NEW_RECORD();
    createRecordPromsie.then(data => {
      setIsModelOpen(true);
    });
  };

  const getUserResponse = new Promise((resolve, reject) => {
    resolve();
  });

  const confirmAddRecord = event => {
    event.preventDefault();
    //resolve the promise after the button click
    console.log("Added Existing record");
    getUserResponse.then(data => {
      setIsModelOpen(false);
    }); //this turns out to be undefined
  };

  const renderModal = () => {
    return (
      <div>
        <p>Record Exists would you like to add them to the group?</p>
        <button onClick={confirmAddRecord}>Add Existing record !</button>
      </div>
    );
  };

  return (
    <div className="App">
      <p>Add record by pressing this button</p>
      <button onClick={createRecord}>Create record </button>
      {isModalOpen ? renderModal() : ""}
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Network.js

export const ADD_NEW_RECORD = async () => {
  //checking from an API of record exists

  return new Promise((resolve, reject) => {
    setTimeout(() => {
      console.log("Record Exists");
      resolve("Record Exists");
    }, 1000);
  });
};