React と Styled Components を使用して美しいトースト メッセージ コンポーネントを作成する方法は?


トースト通知は、ユーザーにフィードバックを提供するもう 1 つの方法です.通常は短いメッセージが含まれており、CTA が付随することもあります.

この記事の目的は、react-hot-toaststyled-components を使用して、見栄えの良いトースト メッセージを作成する方法を説明することです 😉

プロジェクトの初期化




npx create-react-app toast-notification


依存関係をインストールする



  • トースト通知機能を取得するための react-hot-toast

  • スタイリングのニーズには styled-components

  • yarn add react-hot-toast styled-components
    


    定数



    デフォルトのタイトル、デフォルトの説明、バリアントの列挙型がこのファイルに保存されます.

    // path: src/components/toast-notification/data.js
    export const variants = {
      SUCCESS: "Success",
      WARNING: "Warning",
      QUESTION: "Question",
      FAIL: "Fail",
    };
    
    export const DEFAULT_TITLE = {
      Success: "Well done!",
      Warning: "Warning!",
      Question: "Hi there!",
      Fail: "Oh snap!",
    };
    
    export const DEFAULT_DESCRIPTION = {
      Success: "You successfully read this important message.",
      Warning: "Sorry! There was a problem with your request.",
      Question: "Do you have a problem? Just use this contact form.",
      Fail: "Change a few things up and try submitting again.",
    };
    


    アプリ コンポーネント


    Form & Toaster コンポーネントは App コンポーネント内で呼び出されます.

    // path: src/App.js
    
    // External
    import { Toaster } from "react-hot-toast";
    
    // Components
    import Form from "./components/form";
    
    // Styles
    import { AppStyles } from "./styles";
    
    const App = () => {
      return (
        <AppStyles>
          <Form />
          <Toaster position="bottom-left" gutter={56} />
        </AppStyles>
      );
    };
    
    export default App;
    


    トースト通知コンポーネント



    トースト通知コンポーネントには、トースト通知のスタイルが含まれています.

    // path: src/components/toast-notification/index.js
    
    import React from "react";
    
    // External
    import toast from "react-hot-toast";
    
    // Components
    import CustomIcon from "../CustomIcon";
    
    // Styles
    import {
      NotificationCard,
      NotificationImage,
      NotificationImageWrapper,
      NotificationContent,
      NotificationTitle,
      NotificationDescription,
      NotificationIconButton,
      BubblesImage,
    } from "../../styles";
    
    const ToastNotification = ({
      t,
      bgColor,
      icon,
      bubbleImage,
      title,
      message,
    }) => {
      // handlers
      const handleDismiss = () => {
        toast.dismiss(t.id);
      };
    
      return (
        <>
          <NotificationImageWrapper>
            <NotificationImage src={icon} alt="" role="presentation" />
          </NotificationImageWrapper>
          <NotificationCard bgColor={bgColor}>
            <BubblesImage src={bubbleImage} alt="" role="presentation" />
            <NotificationContent>
              <NotificationTitle>{title}</NotificationTitle>
              <NotificationDescription>{message}</NotificationDescription>
            </NotificationContent>
            <NotificationIconButton onClick={handleDismiss}>
              <CustomIcon icon="times" />
            </NotificationIconButton>
          </NotificationCard>
        </>
      );
    };
    
    export default ToastNotification;
    


    フォーム コンポーネント



    このコンポーネントには、コンポーネントのテストに使用される入力が含まれています.

    //path: src/components/form/index.js
    
    import React, { useState, useEffect } from "react";
    
    // External
    import toast from "react-hot-toast";
    
    // Components
    import ToastNotification from "../toast-notification";
    
    // Styles
    import {
      Button,
      RadioButtonContainer,
      RadioButtonInput,
      OptionsContainer,
      Container,
    } from "../../styles";
    
    // Image
    import questionImage from "../../images/question.png";
    import successImage from "../../images/success.png";
    import warningImage from "../../images/warning.png";
    import failImage from "../../images/fail.png";
    import greenBubbles from "../../images/green-bubbles.png";
    import redBubbles from "../../images/red-bubbles.png";
    import blueBubbles from "../../images/blue-bubbles.png";
    import yellowBubbles from "../../images/yellow-bubbles.png";
    
    // Constants
    import {
      variants,
      DEFAULT_TITLE,
      DEFAULT_DESCRIPTION,
    } from "../ToastNotification/data";
    
    const Form = () => {
      const [currentVariant, setCurrentVariant] = useState(variants.SUCCESS);
      const [title, setTitle] = useState(DEFAULT_TITLE.SUCCESS);
      const [message, setMessage] = useState(DEFAULT_DESCRIPTION.SUCCESS);
    
      // change title and message when notification variant changes
      useEffect(() => {
        setTitle(DEFAULT_TITLE[currentVariant]);
        setMessage(DEFAULT_DESCRIPTION[currentVariant]);
      }, [currentVariant]);
    
      // show appropriate toast notification as per the variant
      const showToastNotification = () => {
        if (currentVariant === variants.SUCCESS) {
          toast.custom(t => (
            <ToastNotification
              t={t}
              icon={successImage}
              bubbleImage={greenBubbles}
              bgColor="#76bf4c"
              title={title}
              message={message}
            />
          ));
        }
    
        if (currentVariant === variants.QUESTION) {
          toast.custom(t => (
            <ToastNotification
              t={t}
              icon={questionImage}
              bubbleImage={blueBubbles}
              bgColor="#B8B5FF"
              title={title}
              message={message}
            />
          ));
        }
    
        if (currentVariant === variants.WARNING) {
          toast.custom(t => (
            <ToastNotification
              t={t}
              icon={warningImage}
              bubbleImage={yellowBubbles}
              bgColor="#FCA652"
              title={title}
              message={message}
            />
          ));
        }
        if (currentVariant === variants.FAIL) {
          toast.custom(t => (
            <ToastNotification
              t={t}
              icon={failImage}
              bubbleImage={redBubbles}
              bgColor="#F05454"
              title={title}
              message={message}
            />
          ));
        }
      };
    
      // handlers
      const handleVariantChange = e => {
        setCurrentVariant(e.target.name);
      };
    
      const handleTitleChange = e => {
        setTitle(e.target.value);
      };
    
      const handleMessageChange = e => {
        setMessage(e.target.value);
      };
    
      return (
        <>
          <OptionsContainer>
            {Object.values(variants).map(variant => (
              <RadioButtonContainer key={variant}>
                <RadioButtonInput
                  type="radio"
                  id={variant}
                  name={variant}
                  checked={currentVariant === variant}
                  onChange={handleVariantChange}
                />
                <label htmlFor={variant}>{variant}</label>
              </RadioButtonContainer>
            ))}
          </OptionsContainer>
          <br />
          <Container>
            <label htmlFor="title-field">Title</label>
            <input
              id="title-field"
              type="text"
              value={title}
              onChange={handleTitleChange}
            />
            <label htmlFor="message-field">Message</label>
            <textarea
              id="message-field"
              rows="6"
              value={message}
              onChange={handleMessageChange}
            ></textarea>
          </Container>
          <Button
            isSelected={!(!title || !message)}
            onClick={showToastNotification}
          >
            Show Toast!
          </Button>
        </>
      );
    };
    
    export default Form;
    


    結論



    これで、洗練された外観のアラート通知が実装されました. Code は Github で入手できます.以下のコメントで貴重なフィードバックをお待ちしております.

    それでは👋🏻 このコンポーネント シリーズの次の記事でお会いしましょう!

    ハッピーコーディング&安全に! ✨

    私に従ってください & もっと!

    この記事は私の website でも読むことができます