Javascript 如何使异步/等待函数在React中显示对话框?

Javascript 如何使异步/等待函数在React中显示对话框?,javascript,reactjs,Javascript,Reactjs,我有一个应用程序,它可以打开一个对话框,但是你必须将对话框组件嵌入到父窗体中,代码分散在父组件周围 因此,我希望将所有对话框代码放在一个单独的文件中,并通过异步/等待调用显示它 用户可以单击一个按钮打开对话框,输入一个值,单击OK,然后将一些内容写入数据库-例如 async function clickItem() { const ret = await getValue(initialValue) if (ret.ok) { // ret.value has new value

我有一个应用程序,它可以打开一个对话框,但是你必须将对话框组件嵌入到父窗体中,代码分散在父组件周围

因此,我希望将所有对话框代码放在一个单独的文件中,并通过异步/等待调用显示它

用户可以单击一个按钮打开对话框,输入一个值,单击OK,然后将一些内容写入数据库-例如

async function clickItem() {
  const ret = await getValue(initialValue)
  if (ret.ok) {
    // ret.value has new value - update db etc
  } else {
    // user hit cancel
  }
}
有些规定—

  • 将对话框作为功能组件写入,并带有useState挂钩等,因此可以完全动态
  • 将初始字段值传递给包装函数
  • 包装器函数返回一个用对象{ok:true/false,相关字段值…}解析的承诺
  • 将对话框代码封装在一个文件中
  • 不需要像react-modal一样将组件嵌入父组件中,只需调用一个fn将其呈现并插入DOM即可
  • 带有jest和/或cypress的可测试组件
有一个项目,它几乎实现了我想要的功能,但您不能使用useState,也不能将React组件传递给它,因此仅限于静态对话框


那么,您将如何着手做这样的事情呢?

我最终得到了一个简单的版本,它不需要任何样式——这里是一个代码沙盒

包装器函数只是创建一个承诺,并将
resolve
回调传递给对话框组件,当用户点击OK或Cancel时,对话框组件调用resolve

如果将所有内容放在一个文件中,则如下所示-

import React from "react";
import ReactDOM from "react-dom";

function App() {
  async function clickGetValue() {
    const ret = await getValue(3);
    console.log(ret);
  }
  return (
    <div className="App">
      <button onClick={clickGetValue}>Get Value</button>
    </div>
  );
}

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


function GetValue({ resolve, initialValue = 0 }) {
  const [value, setValue] = React.useState(initialValue);
  function clickPlus() {
    setValue(value => value + 1);
  }
  function clickMinus() {
    setValue(value => value - 1);
  }
  function clickOK() {
    removeDialog();
    resolve({ ok: true, value });
  }
  function clickCancel() {
    removeDialog();
    resolve({ ok: false });
  }
  return (
    <div id="getValue">
      <span id="getValue-value">{value}</span>
      <button onClick={clickPlus}>+1</button>
      <button onClick={clickMinus}>-1</button>
      <button onClick={clickOK}>OK</button>
      <button onClick={clickCancel}>Cancel</button>
    </div>
  );
}

export default function getValue(initialValue) {
  return new Promise((resolve, reject) => {
    addDialog(initialValue, resolve);
  });
}

function addDialog(initialValue, resolve) {
  const body = document.getElementsByTagName("body")[0];
  const div = document.createElement("div");
  div.setAttribute("id", "getValue-container");
  body.appendChild(div);
  ReactDOM.render(
    <GetValue initialValue={initialValue} resolve={resolve} />,
    div
  );
}

function removeDialog() {
  const div = document.getElementById("getValue-container");
  const body = document.getElementsByTagName("body")[0];
  body.removeChild(div);
}
从“React”导入React;
从“react dom”导入react dom;
函数App(){
异步函数clickGetValue(){
const ret=等待获取值(3);
控制台日志(ret);
}
返回(
获得价值
);
}
const rootElement=document.getElementById(“根”);
render(,rootElement);
函数GetValue({resolve,initialValue=0}){
const[value,setValue]=React.useState(initialValue);
函数clickPlus(){
设置值(值=>值+1);
}
函数click减号(){
设置值(值=>值-1);
}
函数clickOK(){
removeDialog();
解析({ok:true,value});
}
函数clickCancel(){
removeDialog();
解析({ok:false});
}
返回(
{value}
+1
-1
好啊
取消
);
}
导出默认函数getValue(initialValue){
返回新承诺((解决、拒绝)=>{
addDialog(初始值,解析);
});
}
函数addDialog(初始值,解析){
const body=document.getElementsByTagName(“body”)[0];
const div=document.createElement(“div”);
div.setAttribute(“id”、“getValue容器”);
附体儿童(div);
ReactDOM.render(
,
div
);
}
函数removeDialog(){
const div=document.getElementById(“getValue容器”);
const body=document.getElementsByTagName(“body”)[0];
身躯,离体儿童(分区);;
}

这看起来像是您想要的:@user574820谢谢-我最终为它制作了自己的小图库,但他们的看起来更坚固,请参见