首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何解决错误:无法在呈现不同组件(“其他组件”)时更新组件(“component”)

如何解决错误:无法在呈现不同组件(“其他组件”)时更新组件(“component”)
EN

Stack Overflow用户
提问于 2022-10-26 12:37:56
回答 1查看 39关注 0票数 0

我正在构建一个带有尾风的动态警报UI。我希望发出此警报,以便在发出所有请求时可以在任何地方使用。我还将警报与全局状态中的值结合起来。总的来说,它运行得很好,但是有以下几点警告:

这是使用redux工具的全局警报状态:

代码语言:javascript
复制
import { createSlice } from '@reduxjs/toolkit';

const uiSlice = createSlice({
    name: 'UI',
    initialState: {
        offcanvasVisible: false,
        alert: {
            isShow: false,
            variant: '',
            message: '',
        },
    },
    reducers: {
        offcanvasToggle: (state) => {
            state.offcanvasVisible = !state.offcanvasVisible;
        },
        showAlert: (state, action) => {
            state.alert.isShow = true;
            state.alert.message = action.payload.message;
            state.alert.variant = action.payload.variant;
        },
        closeAlert: (state) => {
            state.alert.isShow = false;
            state.alert.message = '';
            state.alert.variant = '';
        },
    },
});

export const { offcanvasToggle, showAlert, closeAlert } = uiSlice.actions;
export default uiSlice.reducer;

警报组件中的下列代码:

代码语言:javascript
复制
import { BiNoEntry } from 'react-icons/bi';
import { IoCloseSharp } from 'react-icons/io5';
import { BsCheckCircleFill, BsFillInfoCircleFill } from 'react-icons/bs';
import { useDispatch, useSelector } from 'react-redux';
import { closeAlert } from '../../store/ui-slice';
import { useEffect, useState } from 'react';

const Alert = () => {
    const [showState, setShowState] = useState(false);
    const [variantState, setVariantState] = useState('');
    const [messageState, setMessageState] = useState('');
    const [classes, setClasses] = useState('');

    const dispatch = useDispatch();
    const { variant, message, isShow } = useSelector((state) => state.ui.alert);

    useEffect(() => {
        if (!isShow) return;

        setShowState(isShow);
        setVariantState(variant);
        setMessageState(message);

        if (variant === 'info') {
            setClasses('bg-blue-400 border-blue-500');
        }

        if (variant === 'success') {
            setClasses('bg-green-400 border-green-500');
        }

        if (variant === 'failed') {
            setClasses('bg-red-400 border-red-500');
        }
    }, [isShow, variant, message]);

    return (
        <div
            className={`${
                !showState && 'hidden'
            } container-custom w-full py-4 text-white flex flex-row gap-2 items-center justify-between ${classes}`}
        >
            <div className="flex flex-row gap-2 items-center">
                <span>
                    {variantState === 'info' ? (
                        <BsFillInfoCircleFill size="24" />
                    ) : variantState === 'success' ? (
                        <BsCheckCircleFill size="24" />
                    ) : variantState === 'failed' ? (
                        <BiNoEntry size="24" />
                    ) : (
                        ''
                    )}
                </span>
                {messageState}
            </div>
            <button
                onClick={() => {
                    dispatch(closeAlert());
                }}
                className="text-white"
            >
                <IoCloseSharp color="white" size="24" />
            </button>
        </div>
    );
};

export default Alert;

联系人组件中的代码:

代码语言:javascript
复制
/* eslint-disable jsx-a11y/iframe-has-title */
import LandingLayout from '../../components/Layout/LandingLayout';
import Breadcrumb from '../../components/UI/Breadcrumb';
import Input from '../../components/Form/Input';
import TextArea from '../../components/Form/TextArea';
import { AiOutlineWhatsApp } from 'react-icons/ai';
import { BsInstagram } from 'react-icons/bs';
import {
    MdOutlineAddLocationAlt,
    MdOutlineEmail,
    MdPhone,
} from 'react-icons/md';
import Button from '../../components/UI/Button';
import { useForm } from 'react-hook-form';
import { useDispatch, useSelector } from 'react-redux';
import {
    sendingEmail,
    turnOffLoadingSendEmail,
    turnOnLoadingSendEmail,
} from '../../store/landing-slice';
import Spin from '../../components/UI/Spin';
import { showAlert } from '../../store/ui-slice';

const Kontak = () => {
    const dispatch = useDispatch();
    const { loading, success, error } = useSelector(
        (state) => state.landing.sendEmail
    );

    const {
        register,
        handleSubmit,
        formState: { errors, isValid },
        reset,
    } = useForm({
        mode: 'all',
    });

    if (success !== null) {
        dispatch(showAlert({ variant: 'success', message: success.message }));
    }

    const onSubmit = (data) => {
        if (!isValid) return;

        dispatch(turnOnLoadingSendEmail());

        setTimeout(() => {
            dispatch(sendingEmail(data));
            dispatch(turnOffLoadingSendEmail());
            reset();
        }, 1000);
    };

    return (
        <LandingLayout>
            <Breadcrumb title="Kontak Kami" />
            <section className="container-custom py-10 w-full h-[450px] overflow-hidden">
                <iframe
                    src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3960.687915874803!2d107.64700641530236!3d-6.927857094994467!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x2e68e80a699f1971%3A0xca4c51951a56650c!2sPanti%20Asuhan%20Al-Hidayah!5e0!3m2!1sid!2sid!4v1666696368586!5m2!1sid!2sid"
                    width="100%"
                    height="100%"
                    style={{ border: 0 }}
                    allowFullScreen=""
                    loading="lazy"
                    referrerPolicy="no-referrer-when-downgrade"
                />
            </section>
            <section className="container-custom py-4 w-full flex flex-col gap-10 md:flex-row-reverse">
                <form onSubmit={handleSubmit(onSubmit)} className="w-full">
                    <h2 className="text-gray-700 text-lg mb-3">
                        Hubungi kami melalui form dibawah ini.
                    </h2>
                    <div className="flex flex-col lg:flex-row lg:gap-3">
                        <Input
                            options={{
                                ...register('name', {
                                    required: 'Nama Lengkap tidak boleh kosong',
                                }),
                            }}
                            id="name"
                            label="Nama Lengkap"
                            requireIcon="true"
                            hasError={!!errors?.name}
                            errorMessage={errors?.name?.message}
                        />
                        <Input
                            options={{
                                ...register('email', {
                                    required: 'E-Mail tidak boleh kosong',
                                    pattern: {
                                        value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
                                        message: 'Invalid email address',
                                    },
                                }),
                            }}
                            id="email"
                            label="E-Mail"
                            requireIcon="true"
                            hasError={!!errors?.email}
                            errorMessage={errors?.email?.message}
                        />
                    </div>
                    <Input
                        options={{
                            ...register('subject', { required: 'Subjek tidak boleh kosong' }),
                        }}
                        id="subject"
                        label="Subjek"
                        requireIcon="true"
                        hasError={!!errors?.subject}
                        errorMessage={errors?.subject?.message}
                    />
                    <TextArea
                        id="keterangan"
                        label="Keterangan"
                        options={{
                            ...register('keterangan'),
                            rows: '4',
                        }}
                    ></TextArea>
                    <Button
                        className="flex gap-2"
                        options={{
                            type: 'submit',
                            disabled: !isValid,
                        }}
                    >
                        {loading && <Spin />}
                        Kirim
                    </Button>
                </form>
                <div className="w-full flex flex-col gap-2 md:gap-4">
                    <div className="flex flex-row gap-2">
                        <span className="self-start rounded-full bg-gray-300 text-gray-700 p-3">
                            <MdOutlineAddLocationAlt size={32} />
                        </span>
                        <div className="flex flex-col gap-1">
                            <h3 className="pt-5 font-semibold text-[17px]">Alamat</h3>
                            Jl. Trs. St. Kiaracondong, RT.02/RW.08, Kebun Jayanti, Kec.
                            Kiaracondong, Kota Bandung, Jawa Barat 40281
                        </div>
                    </div>
                    <div className="flex flex-row gap-2">
                        <span className="self-start rounded-full bg-gray-300 text-gray-700 p-3">
                            <MdPhone size={32} />
                        </span>
                        <div className="flex flex-col gap-1">
                            <h3 className="pt-5 font-semibold text-[17px]">Telepon</h3>
                            022 7333116
                        </div>
                    </div>
                    <div className="flex flex-row gap-2">
                        <span className="self-start rounded-full bg-gray-300 text-gray-700 p-3">
                            <AiOutlineWhatsApp size={32} />
                        </span>
                        <div className="flex flex-col gap-1">
                            <h3 className="pt-5 font-semibold text-[17px]">Whatsapp</h3>
                            0882 43556 7721
                        </div>
                    </div>
                    <div className="flex flex-row gap-2">
                        <span className="self-start rounded-full bg-gray-300 text-gray-700 p-3">
                            <BsInstagram size={32} />
                        </span>
                        <div className="flex flex-col gap-1">
                            <h3 className="pt-5 font-semibold text-[17px]">Instagram</h3>
                            yayasan_alhidayah
                        </div>
                    </div>
                    <div className="flex flex-row gap-2">
                        <span className="self-start rounded-full bg-gray-300 text-gray-700 p-3">
                            <MdOutlineEmail size={32} />
                        </span>
                        <div className="flex flex-col gap-1">
                            <h3 className="pt-5 font-semibold text-[17px]">E-Mail</h3>
                            alhidayahkircon@gmail.com
                        </div>
                    </div>
                </div>
            </section>
        </LandingLayout>
    );
};

export default Kontak;

我把警报放进了海军:

代码语言:javascript
复制
import { Link } from 'react-router-dom';
import Logo from '../UI/Logo';
import { FiMenu, FiPhone } from 'react-icons/fi';
import Button from '../UI/Button';
import Dropdown from '../UI/Dropdown';
import { BiDonateHeart } from 'react-icons/bi';
import { AiOutlineHistory } from 'react-icons/ai';
import Alert from '../UI/Alert';

const Navbar = (props) => {
    return (
        <header className="sticky top-0 z-10 bg-white border-b-2 border-slate-200">
            <Alert />
            <div className="container-custom flex justify-between items-center">
                <div className="w-36 pl-2 md:pl-0">
                    <Link to="/">
                        <Logo />
                    </Link>
                </div>
                <ul className="hidden lg:flex font-medium">
                    <li className="mr-1 hover:bg-gray-100 py-2 px-4 rounded-md">
                        <Link to={'/'}>Beranda</Link>
                    </li>
                    <li className="mr-1 hover:bg-gray-100 py-2 px-4 rounded-md">
                        <Link to={'/kegiatan'}>Kegiatan</Link>
                    </li>
                    <li className="mr-1 hover:bg-gray-100 py-2 px-4 rounded-md">
                        <Dropdown label="Donasi">
                            <li className="block px-4 py-2 hover:bg-gray-100">
                                <Link className="flex items-center" to="/donasi">
                                    <span className="mr-3">
                                        <BiDonateHeart />
                                    </span>
                                    Formulir Donasi
                                </Link>
                            </li>
                            <li className="block px-4 py-2 hover:bg-gray-100">
                                <Link className="flex items-center" to="/cek-donasi">
                                    <span className="mr-3">
                                        <AiOutlineHistory />
                                    </span>
                                    <p>Cek Donasi</p>
                                </Link>
                            </li>
                        </Dropdown>
                    </li>
                    <li className="mr-1 hover:bg-gray-100 py-2 px-4 rounded-md">
                        <Dropdown label="Tentang Kami">
                            <li className="block px-4 py-2 hover:bg-gray-100">
                                <Link to="/profil-lembaga">Profil Lembaga</Link>
                            </li>
                            <li className="block px-4 py-2 hover:bg-gray-100">
                                <Link to="/visi-misi">Visi & Misi</Link>
                            </li>
                            <li className="block px-4 py-2 hover:bg-gray-100">
                                <Link to="/galeri">
                                    <p>Galeri</p>
                                </Link>
                            </li>
                            <li className="block px-4 py-2 hover:bg-gray-100">
                                <Link to="/kontak">Hubungi Kami</Link>
                            </li>
                        </Dropdown>
                    </li>
                </ul>
                <div className="hidden lg:grid grid-cols-2 gap-1">
                    <a
                        className="flex items-center mr-1 hover:bg-gray-100 py-2 px-4 rounded-md"
                        href="tel:+0222334645"
                    >
                        <FiPhone size={'24'} />
                        <span className="ml-2">022 2334645</span>
                    </a>
                    <Button
                        className="flex justify-center items-center"
                        options={{
                            type: 'link',
                            href: '/donasi',
                        }}
                    >
                        Donasi
                        <span className="ml-1">
                            <BiDonateHeart />
                        </span>
                    </Button>
                </div>
                <div className="lg:hidden" onClick={props.offcanvasToggle}>
                    <FiMenu size={32} />
                </div>
            </div>
        </header>
    );
};

export default Navbar;

下面是UI应该是什么样子:

首先,我感谢你被石化了

我希望我能用最好的方式来实现警报,而没有像这样的警告。

EN

回答 1

Stack Overflow用户

发布于 2022-10-26 12:55:28

这是因为您对状态的更新是级联的。您的第一个set将导致DOM更新。更新尚未完成,因此您的第二个(或第三个) set也试图更新DOM,并导致冲突。

我发现,当我同时更新多个状态变量时,最好使用useReducer而不是useState。然后,您可以设置一个dispatch方法,该方法可以同时更新多个状态位,甚至可以提供多个有条件地进行不同更新的方法。这样,state更新是并发的,并且避免您正在看到的错误。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74207917

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档