簡體   English   中英

在 remix js 中保存數據之前的確認消息

[英]Confirmation message before saving data in remix js

我的saveData.tsx Remix 應用程序中有一個Action function,它將一些數據保存在數據庫表中。 這是文件

import type { ActionArgs } from "@remix-run/node";
import { redirect } from "@remix-run/node";
import { Form, useActionData } from "@remix-run/react";
import React from "react";
import { saveData } from "~/models/data.server";

export const action = async ({ request, params }: ActionArgs) => {
    // do some work, collect the `result` which is a JSON.. and then
await saveData(result);
return redirect (`/to/saveData`);
}

export default function Index() {
 const actionData = useActionData<typeof action>();

 return(
  <div>
    <Form method="post">
     <button type="submit">Upload data</button>
    </Form>
  </div>  
 );
}

所以我真正想做的是,我想在await saveData(result)之前收到一條確認消息。 我將確認消息設置為另一個帶有兩個按鈕SaveCanceltsx文件。 模態在不同的路線上。 例如(/to/confirm.tsx) 我想在保存await saveData(result)之前調用此confirm.tsx 然后,當我單擊confirm.tsx中的“ Save ”按鈕時,我想運行await saveData(result)並將數據保存到數據庫。 反之亦然,當我單擊cancel時,我想取消數據保存並redirectsaveData.tsx

我沒有在confirm.tsx中使用任何ActionLoader函數。 這是confirm.tsx文件

export default function Confirm() {
 return (
  <div>
    <div>
      <h1>Are you sure you want to save the data?</h1>
    </div>
    <div>
      <button>Save</button>
    </div>
    <div>
      <button>Cancel</button>
    </div>
  </div>
 )
}

我最初做的是,我將result作為字符串傳遞給URL ,而沒有在 saveData.tsx 的Action function 中使用await saveData(result) saveData.tsx

export const action = async ({ request, params }: ActionArgs) => {
    // do some work, collect the `result` which is a JSON.. and then
    // await saveData(result); <= did not used save functioin inside this file
return redirect(`/to/${JSON.stringify(result)}/confirm`)
}

我以前使用confirm.tsx路由/to/$data/confirm

然后在confirm.tsx中,我使用了一個Action function。在那個Action function 中,我使用params得到了jsonString 然后JSON.pares編輯jsonString並將 object 傳遞給await saveData(jsonParsedData) 然后在保存數據后,重定向到之前的路由saveData.tsx ,如下所示。

import type { ActionArgs } from "@remix-run/node";
import { redirect } from "@remix-run/node";
import { Form, useActionData } from "@remix-run/react";
import React from "react";
import { saveData } from "~/models/data.server";

export const action = async ({ request, params }: ActionArgs) => {
  const jsonString = params.data;
  const jsonParsedData = JSON.parse(jsonString);

  await saveData(jsonParsedData);
  return redirect(`/to/saveData`);
}

export default function Confirm() {
 return (
  <div>
    <div>
      <h1>Are you sure you want to save the data?</h1>
    </div>
    <div>
      <Form method="post">
        <button>Save</button>
      </Form>
    </div>
    <div>
      <Link to={`/to/saveData`}>
       <button>Cancel</button>
      </Link>
    </div>
  </div>
 )
}

以前的方法有效。 但是以這種方式處理成千上萬的數據是不可能的(將數據傳遞到 URL)。 我只需要在一個文件中完成所有過程,而不需要將數據傳遞到另一個文件中。 我只想使用不同的componant或文件或其他任何東西來控制數據保存確認。

我想我已經清楚地解釋了這個問題,如果不清楚請告訴我如何幫助它進一步解釋。 在這個問題上的幫助將不勝感激..

如果本機警報對您來說不夠 Window.confirm() (我強烈推薦)

if (window.confirm("Do you really want to save?")) {
 run this if user say yes
}

您可以將模態組件導入頁面並有條件地顯示它

例如,觸發action的元素更改為 state:

const [showConfirmationModal, setShowConfirmationModal] = useState(false)

然后你有條件地渲染它

{ showConfirmationModal && <confirmModal confirmCallback={action}></confirmModal> }

或者你可以通過作為道具來展示

<confirmModal show={showConfirmationModal} confirmCallback={action}>

action function 是異步代碼。 您不能在action處理程序中間停止並呈現任何 React 組件。 我懷疑你需要做的是:

  1. 提交表單並處理action ,並將數據返回給組件。
  2. Index組件將跟蹤表單何時提交,以便在返回數據時組件可以觸發確認模式,處理用戶響應,然后發出命令式重定向。

它可能類似於以下內容:

import React from "react";
import type { ActionArgs } from "@remix-run/node";
import { redirect } from "@remix-run/node";
import { Form, useActionData, useTransition } from "@remix-run/react";
import { useNavigate } from "react-router-dom";
import { saveData } from "~/models/data.server";

export const action = async ({ request, params }: ActionArgs) => {
  // do some work, collect the `result`, and then
  return /* JSON data */
}

export default function Index() {
  const data = useActionData<typeof action>();
  const navigate = useNavigate();
  const transition = useTransition();

  const [submitted, setSubmitted] = React.useState(false);
  const [showConfirmSave, setShowConfirmSave] = React.useState(false);

  React.useEffect(() => {
    switch(transition.state) {
      case "submitting":
        if (!submitted) {
          setSubmitted(true);
        }
        break:

      case "idle":
        if (submitted && data) {
          setShowConfirmSave(true);
        }
        break:
    }

    
  }, [data, submitted, setShowConfirmSave, setSubmitted, transition]);

  const confirmHandler = async () => {
    await saveData(result);
    navigate("/to/saveData");
  };

  if (showConfirmSave) {
    return <Confirm onConfirm={confirmHandler} />
  }

  return(
    <div>
      <Form method="post">
        <button type="submit">Upload data</button>
      </Form>
    </div>  
  );
}
import React from "react";

interface ConfirmProps {
  onConfirm: () => void;
}

export default function Confirm({ onConfirm }: ConfirmProps) {
  return (
    <div>
      <div>
        <h1>Are you sure you want to save the data?</h1>
      </div>
      <div>
        <button type="button" onClick={onConfirm}>Save</button>
      </div>
      <div>
        <Link to="/to/saveData">
          <button type="button">Cancel</button>
        </Link>
      </div>
    </div>
  );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM