Dlog

클래스형 컴포넌트 함수형 컴포넌트로 바꾸기

#Study-Group  

리액트 스터디 1주 차 공부 완료에서 말한대로 ― “Class형 컴포넌트를 보수해야할 일이 생길 수도 있으니 Class형 컴포넌트를 함수형 컴포넌트로 바꾸는 것도 공부하면 좋을 것 같다.” ― 클래스 컴포넌트를 함수형 컴포넌트로 바꾸는 연습을 했다.

클래스형 컴포넌트 코드는 다음과 같다. 👇

import React from "react";
import Notification from "./Notification";

const reservation = [
  { id: 1,
    message: "안녕하세요.",
  },
  { id: 2,
    message: "점심 시간입니다.",
  },
  { id: 3,
    message: "곧 미팅이 시작됩니다.",
  },
];

let timer;

class NotificationList extends React.Component {
  constructor(props){
    super(props);

    this.state = {
      notifications: [],
    };
  }

  componentDidMount(){
    const {notifications} = this.state;
    timer = setInterval(() => {
      if(notifications.length < reservation.length){
        const index = notifications.length;
        notifications.push(reservation[index]);
        this.setState({
          notifications: notifications,
        });
      }else{
        clearInterval(timer);
        this.setState({
          notifications: [],
        });
      }
    }, 1000);
  }

  render(){
    return (
      <div>
        {this.state.notifications.map((notification) => {
          return <Notification 
            message={notification.message}
            key={notification.id}
            id={notification.id} />
        })}
      </div>
    )
  }
}

export default NotificationList;
import React from "react";
import styles from "../css/Notification.module.css"

class Notification extends React.Component {
  constructor(props){
    super(props);

    this.state = {};
  }

  // Lifecycle
  componentDidMount(){
    console.log(`${this.props.id} componentDidMount()`);
  }
  componentDidUpdate(){
    console.log(`${this.props.id} componentDidUpdate()`);

  }
  componentWillUnmount(){
    console.log(`${this.props.id} componentWillUnMount()`);
  }
  
  render() {
    return (
      <div className={styles.wrapper}>
        <span className={styles.messageTxt}>{this.props.message}</span>
      </div>
    );
  }
}

export default Notification;


위의 코드를 함수형 컴포넌트로 바꾸었다. 👇

import { useState, useEffect } from "react";
import styled from "styled-components";

const Msg = styled.p`
  margin: 2rem 0;
`;
const Title = styled.h3`
  margin: 4rem 0 3.2rem;
  font-weight: 700;
  font-size: 2rem;
`;

const Notification = () => {
  const txt = ["안녕하세요.", "점심시간입니다.", "퇴근하세요."];
  const [notifications, setNotification] = useState([]);

  let timer;

  useEffect(() => {
    const index = notifications.length;
    if(notifications.length < txt.length){
        timer = setInterval(() => {
            setNotification([...notifications, txt[index]])
        }, 2000);
    } 
    return () => clearInterval(timer);

}, [notifications])

  return (
    <div>
      <Title>📌 알람 📌</Title>
      {notifications.map((msg, idx) => {
        return <Msg key={idx}>{msg}</Msg>
      })}
    </div>
  );
};

export default Notification;

이 최종 완성된 코드는 같이 리액트 스터디를 하고 있는 스터디원(감사합니다. 쩨로님!)의 코드를 참고하여 작성했다.

처음 내가 짠 코드는 아래과 같다. useInterval을 응용해서 만들었다. 동작은 되는데… 코드가 좋아보이질 않았다. 😂 분명 더 간결한 방법이 있을 거라고 생각했다. 정말 골치가 아팠는데, 다른 스터디원의 코드를 보고 힌트를 얻었다.

스터디에서 클래스형 컴포넌트를 함수형 컴포넌트로 바꿔보자고 제안하길 잘했다. 😊

import { useState, useRef, useEffect } from "react";
import styled from "styled-components";

const Msg = styled.p`
  margin: 2rem 0;
`;
const Title = styled.h3`
  margin: 4rem 0 3.2rem;
  font-weight: 700;
  font-size: 2rem;
`;

const NotificationListCopy = () => {
  const txt = ["안녕하세요.", "점심시간입니다.", "퇴근하세요."];

  const [count, setCount] = useState(0);
  const [notif] = useState([]);
  const callback = () => setCount(count + 1);
  const savedCallback = useRef();

  useEffect(() => {
    savedCallback.current = callback;
  }, [txt]);

  useEffect(() => {
    function tick() {
      savedCallback.current();
      if (notif.length < txt.length) {
        const index = notif.length;
        notif.push(txt[index]);
      }
    }
    if (2000 !== null) {
      let timer = setInterval(tick, 2000);
      return () => clearInterval(timer);
    }
  }, [2000]);

  return (
    <div>
      <Title>📌 알람 📌</Title>
      {notif.map((msg, idx) => {
        return <Msg key={idx}>{msg}</Msg>
      })}
    </div>
  );
};


export default NotificationListCopy;