Front-end/React

[React] 코딩애플 blog-part2-4 (Lifecycle & Hook)

hyebin Lee 2021. 12. 28. 20:16

이전 시간 오류 잡기

<a> cannot appear as a descendant of <a>

오류 발생!

원인 : a태그 안에 a태그 넣으면 안된다

<Nav.Link><Link to="/"> Home </Link></Nav.Link>

따라서 이렇게 수정해준다.

<Nav.Link as={Link} to="/"> Home </Nav.Link>

여기서 as 는 react-bottstrap 문법으로 기본 a태그 대신 사용할 HTML태그 혹은 컴포넌트를 집어넣을 수 있다.

 

Lifecycle & Hook

컴포넌트의 Lifecycle인생이다. 😯

컴포넌트가 생성이 되고, 변경이 되면 업데이터가 되고, 삭제가 될 수 있다.

우리는 Lifecycle 중간중간에 hook을 걸 수 있다.

 

hook? 컴포넌트의 인생 중간중간에 뭔가 명령을 줄 수 있다. 🧐

 

컴포넌트가 생성되기 전에 hook! (그전에 이것좀 해줘!) 을 걸 수 있다.

또는

컴포넌트가 삭제되기 전에 hook!

 

 

이전 Lifecycle (참고하기) 

class Detail2 extends React.Component {
  componentDidMount() {
    //마운트가 되었을 때 실행할 코드~
  }
  componentWillUnmount() {
    //컴포넌트가 사라질때 실행 코드~
  }
}

 

useEffect Hook

import 해오기!

import React, { **useEffect**, useState } from "react";

 

1. 컴포넌트가 보일 때, 업데이가 될 때 특정 코드 실행 가능

function Detail(props) {
  useEffect(() => {
    console.log(1111111);
  });

 

2. 컴포넌트가 사라질 때 코드를 실행 가능

useEffect(() => {
    return function test(){
      // 실행할 코드 -> 사라질 때 실행됨
    }
  });

arrow function 도 가능

useEffect(() => {
    return ()=>{
      // 실행할 코드 -> 사라질 때 실행됨
    }
  });

 

3. useEffect 훅을 여러개 사용하고 싶을 때

useEffect(() => {

  });
useEffect(() => {

  });
useEffect(() => {

  });
useEffect(() => {

  });

이렇게 가능!

이때는 순서대로 실행이 된다.

 

 

문제 ! Detail 페이지 방문 후 2초 후에 저번시간에 만든 alert 박스가 사라지게 해보십시오.

hint? 자바스크립트 setTimeout 함수 사용!

let timer = setTimeout(()=>{

    },2000)
//ms단위로, 2000ms -> 2초

 

 

내가 짠 코드

(이전에 모달창 코드 참고 하여 작성하니까 술술 풀렸다..! 신기) 😀

import React, { useEffect, useState } from "react";
import { useHistory, useParams } from "react-router-dom";
import Styled from "styled-components";
import "./Detail.scss";

let Box = Styled.div`
  padding : 20px;
`;

let Title = Styled.h4`
  font-size : 25px;
  color : ${(props) => props.color}
`;

function Detail(props) {
  useEffect(() => {
    console.log(1111111);
    //컴포넌트가 보일 때, 업데이가 될 때 특정 코드 실행 가능
    let timer = setTimeout(() => {
      modalChange(false);
    }, 2000);
  });

  let history = useHistory();
  let { id } = useParams();
  let realID = props.sticker[id].id;
  let [modal, modalChange] = useState(true);

  return (
    <div className="container">
      <Box>
        <Title className="navy">Detail</Title>
      </Box>
      {modal == true ? <Modal /> : modal == false}
      <div className="row">
        <div className="col-md-6">
          <img
            src={require(`./Sketch00${parseInt(id) + 1}.jpg`)}
            width="100%"
          />
        </div>
        <div className="col-md-6 mt-4">
          <h4 className="pt-5">{props.sticker[realID].title}</h4>
          <p>{props.sticker[realID].content}</p>
          <p>{props.sticker[realID].price}</p>
          <p>{props.sticker[id].id}</p>
          <button className="btn btn-danger">Order</button>
          <button
            className="btn"
            onClick={() => {
              history.goBack();
            }}
          >
            Back
          </button>
        </div>
      </div>
    </div>
  );
}
function Modal() {
  return (
    <div className="my-alert">
      <p>재고가 얼마 남지 않았습니다</p>
    </div>
  );
}

export default Detail;

 

 

답안

(Detail.js 파일)

function Detail(){

  let [ alert, alert변경 ] = useState(true);

  useEffect(()=>{
    let 타이머 = setTimeout(()=>{ alert변경(false) }, 2000);
  });
  
  return (
    <HTML많은곳/>
    {
      alert === true
      ? (<div className="my-alert2">
          <p>재고가 얼마 남지 않았습니다</p>
        </div>)
      : null
    }
  )
}

 

 

useEffect에서 버그?

하지만 useEffect에서 버그가 생길 가능서이 있다?

useEffect는 컴포넌트 등장/업데이트 시 실행이 된다.

예를들어 코드를 한번 만들어 보면

let [inputData, inputChange] = useState("");
<input
        onChange={(e) => {
          inputChange(e.target.value);
        }}
      />

input에 입력한 데이터를 inputData에 저장하는 코드이다.

e.target.value 는 input 에 입력된 값이다.

 

 

이럴경우 input 데이터에서 뭔가 입력을 하면 Detail에서 재렌더링, 업데이트가 일어나면서 useEffect도 계속 실행이 된다.

이를 막기 위해서 특정 state가 변경 될 때만 실행해야한다.

(useEffect가 실행될 조건이 필요하다)

 

useEffect(() => {
    console.log(inputData);
    //컴포넌트가 보일 때, 업데이가 될 때 특정 코드 실행 가능
    let timer = setTimeout(() => {
      modalChange(false);
    }, 2000);
  },[modal,inputData]);

이렇게 조건을 주면 alert,inputData state가 변경이 될때만 실행이 된다.

만약 조건이 [ ] 이면, 맞는 조건이 없으므로 업데이트 실행이 안된다.

따라서 등장 시 한번 실행하고 끝나게 된다. (트릭)

 

 

setTimeout 버그?

2초가 지나기도 전에 뒤로가기를 누르면 버그가 발생할 수 있다!

따라서 setTimeout을 사용할 때는 return 으로 타이머를 제거해야한다.

(따라서 timer은 변수로 넣어두는것이 좋다!)

useEffect(() => {
    let timer = setTimeout(() => {
      modalChange(false);
    }, 2000);
    return ()=>{clearTimeout(timer)}
  }, []);