状态更新导致 Next.js 软刷新页面

问题描述 投票:0回答:1

我的 Next.js 项目中有一个使用 Radix UI 的模式组件。使用状态有不同的两种方式绑定输入。问题是当状态更新时,整个页面重新呈现,导致所有状态都被刷新。这是我的代码:

/* eslint-disable */

"use client";

import * as Dialog from "@radix-ui/react-dialog";
import * as Accordion from "@radix-ui/react-accordion";
import * as sanitizeHtml from "sanitize-html";
import "./components.scss";
import { SetStateAction, useEffect, useRef, useState } from "react";
import useFetch from "@/hooks/useFetch";
import HTTPMethod from "http-method-enum";
import Image from "next/image";
import { loading as loadingImg } from "@/public/icons";
import { Review } from "@/mongo/functions/review";
import { User } from "@/mongo/functions/user";
import Link from "next/link";
import Editor from "react-simple-wysiwyg";
import { expandLess } from "@/public/icons";

export default async function CreateReview({
    userProp,
    type,
    currentUserProp,
    existingReviewProp,
    isSelf,
}: {
    userProp: string;
    type: string;
    currentUserProp: string;
    existingReviewProp: string;
    isSelf: boolean;
}) {
    const existingReview: Review = JSON.parse(existingReviewProp);
    const currentUser: User = JSON.parse(currentUserProp);
    const user: User = JSON.parse(userProp);

    const titleRef = useRef("");
    const [stars, setStars] = useState(5);

    const [html, setHtml] = useState("");

    function onChange(e) {
        setHtml(sanitizeHtml(e.target.value));
    }

    const [wizardText, setWizardText] = useState([]);
    const [wizardOpen, setWizardOpen] = useState(true)

    const [data, setData] = useState(null);
    const [error, setError] = useState("");
    const [loading, setLoading] = useState(false);
    const [deleyed, setDeleyed] = useState(false);
    const [aborted, setAborted] = useState(false);

    useEffect(() => {
        if (!error && !loading && data) {
            window.location.reload();
        }
    }, [data, error, loading]);

    const onSubmit = async (e: any) => {
        e.preventDefault();
        useFetch(setData, setError, setLoading, setDeleyed, aborted, {
            url: "/api/reviews/add",
            method: HTTPMethod.POST,
            body: {
                title: titleRef.current.value,
                stars: stars,
                text: html,
                type: type,
                author: currentUser._id,
                recipient: user._id,
                status: "unlisted",
            },
        });
    };

    const onChecked = (e: any, text: string, id: string) => {
        const wizardTextArray = [...wizardText];

        if (e.target.checked) {
            setHtml(html + text);
        } else if (!e.target.checked) {
            const htmlRegex = new RegExp(
                `<span\\s+id=['"]${id}['"][^>]*>.*?<\\/span>`,
                "g"
            );
            console.log(htmlRegex);
            console.log(html.replace(htmlRegex, ""));
            setHtml(html.replace(htmlRegex, ""));
        }
    };

    if (isSelf) {
        return (
            <>
                <h1>You can&apos;t write a review for yourself.</h1>
            </>
        );
    }

    if (existingReview) {
        return (
            <>
                <h1>You&apos;ve already writen review for this user.</h1>
            </>
        );
    }

    if (!currentUser.businessName) {
        return (
            <>
                <h1>Setup your business profile to start rating</h1>
                <button className="standard-clr-btn">
                    <Link href="/app/business">Setup</Link>
                </button>
            </>
        );
    }

    const ReviewWizard = () => {
        return (
            <Accordion.Root
                className="AccordionRoot"
                type="single"
                defaultValue="item-1"
                collapsible
            >
                <Accordion.Item className="AccordionItem" value="item-1">
                    <Accordion.Trigger>
                        Review Wizard (Beta)
                        <span className="toggle-open"> Toggle Open</span>
                    </Accordion.Trigger>
                    <Accordion.Content>
                        {stars === 5 ? (
                            <ul>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="great-work-with">Great to work with! </span>`,
                                                "great-work-with"
                                            )
                                        }
                                    />
                                    <span>Great to work with! </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="loyal-customer">The customer is loyal. </span>`,
                                                "loyal-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is loyal. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="payed-on-time">The customer payed on time. </span>`,
                                                "payed-on-time"
                                            )
                                        }
                                    />
                                    <span>The customer payed on time. </span>
                                </li>
                            </ul>
                        ) : null}
                        {stars === 4 ? (
                            <ul>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="loyal-customer">The customer is loyal. </span>`,
                                                "loyal-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is loyal. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="payed-on-time">The customer paid on time. </span>`,
                                                "payed-on-time"
                                            )
                                        }
                                    />
                                    <span>The customer payed on time. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="below-average-conditions">The work conditions on the property were below average. </span>`,
                                                "below-average-conditions"
                                            )
                                        }
                                    />
                                    <span>
                                        The work conditions on the property were below average.
                                    </span>
                                </li>
                            </ul>
                        ) : null}
                        {stars === 3 ? (
                            <ul>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="disloyal-customer">The customer is disloyal. </span>`,
                                                "disloyal-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is disloyal. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="fault-finding-customer">The customer is fault finding. </span>`,
                                                "fault-finding-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is fault finding. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="late-pay">The customer did not pay on time. </span>`,
                                                "late-pay"
                                            )
                                        }
                                    />
                                    <span>The customer did not pay on time. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="payed-on-time">The customer paid on time. </span>`,
                                                "payed-on-time"
                                            )
                                        }
                                    />
                                    <span>The customer payed on time. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="below-average-conditions">The work conditions on the property were below average. </span>`,
                                                "below-average-conditions"
                                            )
                                        }
                                    />
                                    <span>
                                        The work conditions on the property were below average.
                                    </span>
                                </li>
                            </ul>
                        ) : null}
                        {stars === 2 ? (
                            <ul>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="disloyal-customer">The customer is disloyal. </span>`,
                                                "disloyal-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is disloyal. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="fault-finding-customer">The customer is fault finding. </span>`,
                                                "fault-finding-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is fault finding. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="late-pay">The customer did not pay on time. </span>`,
                                                "late-pay"
                                            )
                                        }
                                    />
                                    <span>The customer did not pay on time. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="below-average-conditions">The work conditions on the property were below average. </span>`,
                                                "below-average-conditions"
                                            )
                                        }
                                    />
                                    <span>
                                        The work conditions on the property were below average.
                                    </span>
                                </li>
                            </ul>
                        ) : null}
                        {stars === 1 ? (
                            <ul>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="disloyal-customer">The customer is disloyal. </span>`,
                                                "disloyal-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is disloyal. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="fault-finding-customer">The customer is fault finding. </span>`,
                                                "fault-finding-customer"
                                            )
                                        }
                                    />
                                    <span>The customer is fault finding. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="no-pay">The customer did not pay. </span>`,
                                                "no-pay"
                                            )
                                        }
                                    />
                                    <span>The customer did not pay. </span>
                                </li>
                                <li>
                                    <input
                                        type="checkbox"
                                        onClick={(e) =>
                                            onChecked(
                                                e,
                                                `<span id="below-average-conditions">The work conditions on the property were below average. </span>`,
                                                "below-average-conditions"
                                            )
                                        }
                                    />
                                    <span>
                                        The work conditions on the property were below average.
                                    </span>
                                </li>
                            </ul>
                        ) : null}
                    </Accordion.Content>
                </Accordion.Item>
            </Accordion.Root>
        );
    };

    return (
        <Dialog.Root>
            <Dialog.Trigger asChild>
                <button className="standard-clr-btn" style={{ height: 50 }}>
                    Write a review
                </button>
            </Dialog.Trigger>
            <Dialog.Portal>
                <Dialog.Overlay className="DialogOverlay" />
                <Dialog.Content className="DialogContent standard-dialog">
                    {currentUser.isBetaUser ? <ReviewWizard /> : null}
                    {loading && !error ? (
                        <>
                            <Image
                                src={loadingImg}
                                alt="Loading..."
                                className="popup-loading"
                            />
                            {deleyed ? (
                                <div>
                                    <h1>Your request is taking longer than usual</h1>
                                    <p>
                                        We are still working to complete it. You can cancel this
                                        request and try again if you like. Note you will lose any
                                        data you submited.
                                    </p>
                                    <button
                                        onClick={() => setAborted(true)}
                                        className="standard-clr-btn"
                                    >
                                        Cancel
                                    </button>
                                </div>
                            ) : null}
                        </>
                    ) : (
                        <form onSubmit={(e) => onSubmit(e)}>
                            {error ? <span className="error-text">{error} </span> : null}
                            <label>How many stars?</label>
                            <select
                                value={stars}
                                onChange={(e) => setStars(Number(e.target.value))}
                                className="standard-dropdown"
                            >
                                <option value={1}>1 star</option>
                                <option value={2}>2 stars</option>
                                <option value={3}>3 stars</option>
                                <option value={4}>4 stars</option>
                                <option value={5} selected>
                                    5 stars
                                </option>
                            </select>
                            <label>What&apos;s your title?</label>
                            <input
                                className="standard-input"
                                name="title"
                                ref={titleRef}
                                placeholder="Great to work with!"
                            />
                            <label>What do you want to say?</label>
                            <Editor value={html} onChange={onChange} />
                            <button
                                className="standard-clr-btn"
                                aria-label="Send"
                                type="submit"
                                style={{ height: 50 }}
                            >
                                Publish
                            </button>
                        </form>
                    )}
                    <Dialog.Close asChild>
                        <button className="IconButton" aria-label="Close">
                            Close
                        </button>
                    </Dialog.Close>
                </Dialog.Content>
            </Dialog.Portal>
        </Dialog.Root>
    );
}

奇怪的是,引用并没有导致整个页面只渲染具有状态的区域。

javascript reactjs typescript next.js state
1个回答
0
投票

在单页应用程序(例如 React.js)中使用

window.location.reload();
违背了创建单页应用程序的初衷,请考虑将其删除。对用作
data
依赖的以下状态
error
loading
useEffect
的任何更新都将导致您的窗口重新加载,进而重置您的所有应用程序状态。

© www.soinside.com 2019 - 2024. All rights reserved.