728x90

토스트 메시지 띄우기 간단 예제 (ReactDOM.createPortal)

들어가며

  • 리액트(React.js)를 이용하여 구현해본 토스트(Toast) 메시지 띄우기 간단 예제 코드를 올려본다.
  • 기능을 구현하기 위해 @react-dom@ 패키지의 @createPortal@ 함수를 사용하였다.

 

코드

 

App.jsx
import React from 'react';
import Toast from './Toast';

function App() {
  const [isToastVisible, setIsToastVisible] = React.useState(false);

  function handleEnrol() {
    setIsToastVisible(true);
    
    setTimeout(() => {
      setIsToastVisible(false);
    }, 3000);
  }

  return (
    <div id="app">
      { isToastVisible && <Toast message={"You are enrolled successfully! :)"} /> }
      <article>
        <h2>React Course</h2>
        <p>
          A course that teaches you React from the ground up and in great depth!
        </p>
        <button onClick={handleEnrol}>Enrol</button>
      </article>
    </div>
  );
}

export default App;

 

Toast.jsx
  • @react-dom@ 패키지에 있는 @createPortal(content, target)@ 함수는 @index.html@ 파일에 있는 @target@ 요소에 현재 컴포넌트를 반환해준다.
    • 현재 토스트 메시지 컴포넌트가 부모 컴포넌트(@App.jsx@)의 자식 컴포넌트로 있지만, 이 기능을 이용할 경우 @App.jsx@와 동일한 위치로 옮길 수 있다. 
    • 아래의 코드에는 @index.html@ 코드의 @<body>@ 요소에 @Toast@ 컴포넌트를 위치시킨다.
import ReactDOM from "react-dom";

export default function Toast({ message }) {
  return ReactDOM.createPortal(
    <aside className="toast" data-testid="toast">
      <p>{message}</p>
    </aside>,
    document.querySelector('body')
  );
}

 

index.css
@import url('https://fonts.googleapis.com/css2?family=Raleway:wght@400;700&family=Lato:wght@400;700&display=swap');

* {
  box-sizing: border-box;
}

body {
  margin: 0;
  font-family: 'Raleway', sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background: linear-gradient(#180d27, #0c0219);
  color: #e5d9f1;
  min-height: 100vh;
}

#app {
  margin: 2rem auto;
  padding: 1rem;
  max-width: 30rem;
  text-align: center;
  border-radius: 6px;
  background: linear-gradient(#341a89, #3a1967);
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
}

button {
  margin: 0.5rem;
  padding: 0.5rem 1rem;
  border: none;
  border-radius: 4px;
  background: #e5d9f1;
  color: #341a89;
  font-family: 'Lato', sans-serif;
  font-size: 1rem;
  font-weight: 700;
  cursor: pointer;
  transition: all 0.2s ease-out;
}

.toast {
  position: absolute;
  top: 2rem;
  left: 3rem;
  padding: 1rem;
  border-radius: 4px;
  background: rgba(118, 234, 189, 0.8);
  color: black;
  box-shadow: 0 0 8px rgba(0, 0, 0, 0.3);
  animation: fade-slide-in-from-left 0.3s ease-out;
}

.toast p {
  margin: 0;
}

@keyframes fade-slide-in-from-left {
  0% {
    opacity: 0;
    transform: translateX(-1rem);
  }
  100% {
    opacity: 1;
    transform: translateX(0);
  } 
}

 

index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Toast Message Example</title>
  </head>
  <body>
    <div id="content">
      <div id="root"></div>
    </div>
    <script type="module" src="/src/main.jsx"></script>
  </body>
</html>

 

참고 사이트

 

createPortal – React

The library for web and native user interfaces

react-ko.dev

 

728x90