일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- til
- array
- react localStorage
- 알고리즘
- Reducer
- es6
- TypeScript
- react
- 자바스크립트
- 프리온보딩
- firebase
- state
- Frontend
- 프론트엔드
- 비트 연산자
- Redux
- Component
- 리액트
- JavaScript
- JS
- 원티드
- 프로그래머스
- v9
- localstorage
- 브라우저
- 컴포넌트
- 타입스크립트
- axios
- 파이어베이스
- CORS
- Today
- Total
도리쓰에러쓰
[React] Lifecycle Hook(예전 문법) vs useEffect(요즘 문법) 본문
[React] Lifecycle Hook(예전 문법) vs useEffect(요즘 문법)
강도리 2022. 1. 18. 14:29저번 게시물에 이어서 작성하겠습니다. (코드 참고)
1. Lifecycle Hook
Component는 '등장 - 업데이트(재렌더링) - 퇴장' 주기가 있습니다.
Lifecycle Hook은 Component의 주기 중간에 명령을 줄 수 있습니다.
가장 유용한 Hook은 componentDidMount()와 componentWillUnmount() 입니다.
class Detail2 extends React.Component {
// Detail2 컴포넌트가 Mount 되었을 때 실행할 코드
componentDidMount() {
}
// Detail2 컴포넌트가 Unmount 되었을 때 실행할 코드
componentWillUnmount() {
}
}
2. useEffect Hook
useEffect Hook은 Component가 mount 되었을 때도 컴포넌트가 update 될 때도 특정 코드를 실행할 수 있습니다.
요즘 React를 개발할 땐 Lifecycle Hook보다 useEffiect Hook을 더 많이 사용합니다.
- 우선 useEffect를 import 합니다.
import React, { useEffect, useState } from 'react';
- 그리고 함수로 호출하여 사용하면 됩니다.
function Detail() {
useEffect(()=>{
// 코드 작성
});
return (
// HTML 코드
)
}
- 여러개 사용하고 싶다면 아래와 같이 작성하면 됩니다.
function Detail() {
useEffect(()=>{
// 첫번째로 실행할 코드
});
useEffect(()=>{
// 두번째로 실행할 코드
});
return (
// HTML 코드
)
}
3. useEffect()를 이용하여 2초 후에 alert 창 사라지게 하기
1) UI를 보이게 혹은 보이지 않게 하는 상태를 state로 저장
let [alert, setAlert] = useState(true);
2) if문 등을 이용해 state가 true일 때만 UI를 보여줍니다.
{
alert === true
? (<div className='my-alert-red'>
<p>재고가 얼마 남지 않았습니다!</p>
</div>)
: null
}
3) state값을 변경하는 함수 setAlert()를 통해 값을 false로 바꿔주면, 2초 뒤에 alert창이 보이지 않게 됩니다.
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
});
- 다음과 같이 alert창이 사라진 것을 확인할 수 있습니다.
🔽
📌 useEffect()를 맨처음 <Detail> load될 때만 실행하게 하고 싶다면?
- 우선 input을 하나 만듭니다.
<input onChange={ (e)=>{ setInputData(e.target.value) } }/>
- input에 입력된 값을 저장하는 변수를 만듭니다.
let [inputData, setInputData] = useState('');
- input에 무언가를 입력하면 업데이트(재렌더링)이 일어나는데 그럴 때마다 useEffect()도 계속 실행됩니다. 확인해보기 위해 임시로 아까 만들어뒀던 useEffect()에 console.log()를 찍어봅시다.
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
console.log('test');
});
- 개발자 도구에서 확인해보면 input에 값을 입력할 때마다 update가 되어 useEffect()가 실행된다는 것을 확인할 수 있습니다.
- useEffect()는 업데이트 될 때마다 실행이 되는데 아래 코드와 같이 특정 state가 변경될 때만 실행되는 실행 조건을 지정하면 됩니다. 그럼 특정 state가 변경되기 전까진 update되어도 useEffect()가 실행되지 않습니다.
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
console.log('test');
}, [alert]);
- 실행 조건인 특정 state를 여러개 작성해도 됩니다.
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
console.log('test');
}, [alert, inputData]);
- 아래 코드와 같이 실행 조건이 빈칸이면 <Detail> 등장 시 한번 실행하고 끝납니다.
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
console.log('test');
}, []);
3-1. setTimeout 주의점
setTimeout을 사용하면 버그가 생길 수 있고, 그 안에 이상한 코드가 들어갈 수도 있어서 꼭 타이머 해제를 해야합니다.
타이머 해제를 위해 위에서 배웠던 'useEffect()의 실행 조건'을 사용하여 작성해봅시다.
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
return ()=>{ clearTimeout(timer) }
}, []);
4. 전체 코드
App.js
/* eslint-disable */
import React, { useState } from 'react'
import { Navbar, Container, Nav, NavDropdown, Button } from 'react-bootstrap';
import './App.css';
import data from './data.js';
import Detail from './Detail.js'
import { Link, Route, Switch } from 'react-router-dom';
function App() {
let [products, setProducts] = useState(data);
return (
<div className="App">
<Navbar bg="light" expand="lg">
<Container>
<Navbar.Brand href="#home">Saint Laurent</Navbar.Brand>
<Navbar.Toggle aria-controls="basic-navbar-nav" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="me-auto">
<Nav.Link as={Link} to="/">Home</Nav.Link>
<Nav.Link as={Link} to="/detail">Detail</Nav.Link>
<NavDropdown title="Dropdown" id="basic-nav-dropdown">
<NavDropdown.Item href="#action/3.1">Action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.2">Another action</NavDropdown.Item>
<NavDropdown.Item href="#action/3.3">Something</NavDropdown.Item>
<NavDropdown.Divider />
<NavDropdown.Item href="#action/3.4">Separated link</NavDropdown.Item>
</NavDropdown>
</Nav>
</Navbar.Collapse>
</Container>
</Navbar>
<Switch>
<Route exact path="/">
<div className='Jumbotron'>
<h1>20% Season Off</h1>
<p>
This is a simple hero unit, a simple jumbotron-style component for calling
extra attention to featured content or information.
</p>
<p>
<Button variant="primary">Learn more</Button>
</p>
</div>
<div className='container'>
<div className='row'>
{
products.map((a, i) => {
return <Card products={a} num={i} key={i}/>
})
}
</div>
</div>
</Route>
<Route path="/detail/:id">
<Detail products={ products }/>
</Route>
<Route path="/:id">
<div>아무말</div>
</Route>
</Switch>
</div>
);
}
function Card(props) {
return(
<div className='col-md-4'>
<img className="img" src={ 'images/img'+ (props.num + 1) +'.jpg' } />
<h4>{ props.products.title }</h4>
<p>{ props.products.content }</p>
<p>{ props.products.price }</p>
</div>
)
}
export default App;
Detail.js
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) {
let { id } = useParams();
let history = useHistory();
let findProduct = props.products.find(function(product) {
return product.id = id;
});
let [alert, setAlert] = useState(true);
let [inputData, setInputData] = useState('');
useEffect(()=>{
let timer = setTimeout(() => { setAlert(false) }, 2000);
return ()=>{ clearTimeout(timer) }
}, []);
return(
<div className='container'>
<Box>
<Title className='red'>상세페이지</Title>
</Box>
<input onChange={ (e)=>{ setInputData(e.target.value) } }/>
{
alert === true
? (<div className='my-alert-red'>
<p>재고가 얼마 남지 않았습니다!</p>
</div>)
: null
}
<div className='row'>
<div className='col-md-6'>
<img className='img' src={ process.env.PUBLIC_URL + '/images/img'+ (Number(findProduct.id) + 1)+'.jpg' } />
</div>
<div className='col-md-6 mt-4'>
<h4 className='pt-5'>{ findProduct.title }</h4>
<p>{ findProduct.content }</p>
<p>{ findProduct.price }</p>
<button className='btn btn-danger'>주문하기</button>
<br />
<br />
<button className='btn btn-danger' onClick={ () => {
history.goBack();
}}>뒤로가기</button>
</div>
</div>
</div>
)
}
export default Detail;
* 이외의 코드는 이전 게시물에 작성된 코드와 일치합니다.
'코딩애플 (React) > 기초수업 (코딩애플) - 2' 카테고리의 다른 글
[React] Ajax 요청방법 - 2 (0) | 2022.01.20 |
---|---|
[React] React에서의 Ajax 요청 방법 / axios 설치 (0) | 2022.01.19 |
[React] SASS 개념, 설치 및 기본 문법 (0) | 2022.01.17 |
[React] styled-components를 이용한 class없는 CSS 스타일링 (0) | 2022.01.12 |
[React] React Router 3 :: URL 파라미터로 상세페이지 100개 만들기 (0) | 2022.01.12 |