라이프 사이클 - 수명주기
컴포넌트의 수명은 페이지에 랜더링 되기 전인 준비 과정 -> 페이지에서 사라질 때 끝남
라이프 사이클 메서드 - 클래스 컴포넌트
함수형 컴포넌트 Hooks 기능을 사용하여 처리
Hooks
1) useState
2) useRef
3) useEffect
마운트, 업데이트, 언마운트
1) 마운트: 페이지에 컴포넌트가 나타남
constructor: 컴포넌트 새로 만들 때마다 호출되는 클래자 생성자 메서드 ->
getDerivedStateFromProps: props에 있는 값은 state에 넣을 때 사용되는 메서드 ->
render: 우리가 준비한 UI를 랜더링하는 메서드 ->
componentDidMount: 컴포넌트 웹 브라우저상에 나타난 후 호출되는 메서드
2) 업데이트: 컴포넌트 정보를 업데이트 - 리렌더링
① props가 변경될 때
② state가 변경될 때
③ 부모 컴포넌트가 리렌더링 될 때
④ this.forceUpdate를 이용하여 강제로 렌더링을 트리거할 때
업데이트 발생
getDerivedStateFromProps: props에 있는 값은 state에 넣을 때 사용되는 메서드 ->
shouldComponentUpdate: 컴포넌트가 리렌더링 해야할지 말아야할지를 결정하는 메서드->
true 반환시 render 호출, false 반환시 여기에서 작업 취소
render ->
getSnapshotBeforeUpdate: 컴포넌트 변화를 DOM에 반영하기 직전에 호출하는 메서드 ->
componentDidupdate -> 컴포넌트의 업데이트 작업이 끝난 후 호출하는 메서드 ->
3) 언마운트: 페이지에서 컴포넌트가 사라짐
언마운트하기
componentWillUnmount:컴포넌트가 웹 브라우저상에서 사라지기 전에 호출되는 메서드
함수형 컴포넌트
useEffect: 컴포넌트가 마운트 됐을 때, 언마운트 됐을 때, 업데이트 될 때 특정작업을 처리하는 hook
userarr-react
App.js
import './App.css';
import UserList from './components/UserList';
import { useState, useRef } from 'react';
import CreateUser from './components/CreateUser';
function App() {
// CreateUser의 입력 Input 상태관리
const [ inputs, setInputs ] =useState({
username:"",
email:"",
});
const onChange = (e) => {
const { name, value } = e.target;
setInputs({
...inputs,
[name]:value
})
console.log(inputs);
}
const { username, email} = inputs;
// useState() 실행 -> arr return
// arr[0] = 상태
// arr[1] = 상태를 변경해주는 함수
const [ users, setUsers ] = useState([
{
id: 1,
username:'green',
email: 'green@gmail.com',
active: false,
},
{
id: 2,
username:'blue',
email: 'blue@gmail.com',
active: false,
},
{
id: 3,
username:'yellow',
email: 'yellow@gmail.com',
active: false,
}
])
const nextId = useRef(4);
// 배열에 새로운 항목을 추가하는 함수
// users배열에 새로운 user객체를 추가
const onCreate= () => {
// 새로운 user객체 생성
// const user = {
// id: nextId.current,
// username,
// email,
// }
const user = {
id:nextId.current,
username,
email,
}
// const arr = [1, 2, 3, 4, 5];
// [1, 2, 3 ,4 ,5 ,6]
// arr = [...arr, 6]
setUsers([...users,user]);
setInputs({
username:"",
email:"",
})
nextId.current +=1; // ref객체는 current에 담겨있음
}
// users배열에 해당 id는 삭제
// filter -> 해당하는 id와 user 객체의 id가 다른 객체만 새배열로 반환
const onDelete = (id) => {
setUsers(users.filter(user=> id !== user.id));
}
const onToggle = (id) => {
// 배열메서드 map
setUsers(users.map(user=> id===user.id ? {...user, active: !user.active} : user))
}
return (
<div className="App">
<CreateUser email={email} username={username} onChange={onChange}
onCreate={onCreate} />
<UserList users={users} onDelete={onDelete} onToggle={onToggle}/>
</div>
);
}
export default App;
App_Reducer.js (Reducer 버전)
import './App.css';
import UserList from './components/UserList';
import { useState, useRef, useReducer } from 'react';
import CreateUser from './components/CreateUser';
const initialState = {
inputs: {
username:"",
email:"",
},
users: [
{
id: 1,
username:'green',
email: 'green@gmail.com',
active: false,
},
{
id: 2,
username:'blue',
email: 'blue@gmail.com',
active: false,
},
{
id: 3,
username:'yellow',
email: 'yellow@gmail.com',
active: false,
}
]
}
function reducer(state, action) {
switch(action.type) {
case "CHANGE_INPUT":
return {
...state,
inputs: {
...state.inputs,
[action.name]: action.value
}
};
case "CREATE_USER":
return {
inputs: initialState.inputs,
users: state.users.concat(action.user)
// users: [...state.users, user]
};
case "DELETE_USER":
return {
...state,
users: state.users.filter(user => user.id !== action.id)
};
case "ACTIVE_USER":
return {
...state,
users: state.users.map(user =>
user.id === action.id ? {...user, active: !user.active } : user)
};
default:
return state;
}
}
function App() {
// useReducer로 상태관리
const [ state, dispatch ] = useReducer(reducer, initialState);
//객체 구조분해할당
const { users } = state;
const { username, email } = state.inputs;
const onChange = (e) => {
const { name, value } = e.target;
dispatch({
type: "CHANGE_INPUT",
name: name,
value: value
})
}
const onCreate = () => {
dispatch({
type: "CREATE_USER",
user: {
id: nextId.current,
username: username,
email: email,
}
})
nextId.current += 1;
}
const nextId = useRef(4);
const onDelete = (id) => {
dispatch({
type: "DELETE_USER",
id: id
})
}
const onToggle = (id) => {
dispatch({
type: "ACTIVE_USER",
id: id
})
}
return (
<div className="App">
<CreateUser email={email} username={username} onChange={onChange}
onCreate={onCreate} />
<UserList users={users} onDelete={onDelete} onToggle={onToggle}/>
</div>
);
}
export default App;
CreateUser.js
import React from 'react';
const CreateUser = ({username, email, onChange, onCreate}) => {
return (
<div>
<input name="username" placeholder="이름" value = {username}
onChange={onChange}/>
<input name="email" placeholder="이메일" value = {email}
onChange={onChange}/>
<button onClick={onCreate}>등록</button>
</div>
);
};
export default CreateUser;
UserList.js
import React, { useEffect } from 'react';
import './UserStyle.css'
const User = ({user, onDelete, onToggle}) => {
useEffect(()=>{
console.log('컴포넌트가 화면에 나타남');
return () => {
console.log('컴포넌트가 화면에서 사라짐');
}
}, [])
return (
<div>
<span className={user.active ? 'active': ""} onClick={()=>{onToggle(user.id) }}>
유저네임: {user.username}
이메일: {user.email}
</span>
<button onClick={()=>{
onDelete(user.id);
}}>삭제</button>
</div>
)
}
const UserList = ({users, onDelete, onToggle}) => {
// const users = [
// {
// id: 1,
// username:'green',
// email: 'green@gmail.com'
// },
// {
// id: 2,
// username:'blue',
// email: 'blue@gmail.com'
// },
// {
// id: 3,
// username:'yellow',
// email: 'yellow@gmail.com'
// }
// ]
return (
<div>
{users.map(user =><User user={user} key={user.id} onDelete={onDelete} onToggle={onToggle}/> )}
{/* <UserList users={users}/> */}
</div>
);
};
export default UserList;
UserStyle.css
.active {
background-color: lightcyan;
}
App2.js
import React, { useEffect, useState } from 'react';
const App2 = (props) => {
const [ count, setCount ] = useState(1);
const [ input, setInput ] = useState("");
useEffect(()=>{
// componentDidMount && cononentDidUpdate
console.log('렌더링 될 때마다 useEffect 호출')
})
// useEffect에 두번 째 인자로 []을 넘겨주면 마운트 될때만 호출됨
// conponentDidMount
useEffect(()=>{
console.log('처음 마운트 될 때만 useEffect 호출')
}, [])
useEffect(()=>{
console.log('배열요소안의 값이 업데이트 되면 useEffect 호출')
}, [count])
const handleCount = () => {
setCount(count+1);
}
const onChange = (e) => {
setInput(e.target.value);
}
return (
<div>
<button onClick={handleCount}>수정하기</button>
<span>count: {count}</span>
<input onChange={onChange} value={input}/>
</div>
);
};
export default App2;
App3.js
import React, { useState } from 'react';
import Timer from './components/Timer';
const App3 = (props) => {
const [showTimer, setShowTimer] = useState(false);
return (
<div>
{ showTimer && <Timer/>}
<button onClick={()=>{setShowTimer(!showTimer)}}>클릭하세요</button>
</div>
);
};
export default App3;
Components/Timer.js
import React, { useEffect } from 'react';
const Timer = (props) => {
// Mount 할 때 호출 componentDidMount
// UnMount할 때 호추 componentWillUnmount
// Update 할 때 호출 componentDidUpdate
useEffect(()=>{
const timer = setInterval(() => {
console.log('타이머 돌아가는중 ...');
}, 1000)
return () => {
clearInterval(timer);
}
}, [])
return (
<div>
타이머를 실행합니다.
</div>
);
};
export default Timer;
App4.js
import React, { Component, useState, useEffect } from 'react';
const App4 = (props) => {
// 클래스 컴포넌트 보이기
const [funcShow, setFuncShow] = useState(true);
return (
<div>
<h1>hello world</h1>
<input type="button" value="클래스 컴포넌트 보이기/안보이기" onClick={()=>setFuncShow(!funcShow)}/>
{ funcShow && <ClassComp initNumber={2}/> }
</div>
);
};
// class컴포넌트 만들기
class ClassComp extends Component {
// state 생성
// props 값을 sate 값으로 지정
state = {
number: this.props.initNumber,
date: new Date().toLocaleTimeString(),
}
// 랜더가 끝난다음 실행사이클 메서드
componentDidMount() {
console.log("class형 컴포넌트 => componentDidMount");
}
// 컴포넌트 UnMount되기 직전 실행사이클 메서드
componentWillUnmount() {
console.log("class형 컴포넌트 => componentWillUnmount");
}
render() {
console.log("class형 컴포넌트 => render")
return(
<div className='container'>
<h2>클래스 컴포넌트</h2>
<p>Number: <span>{this.state.number}</span></p>
<p>Date: <span>{this.state.date}</span></p>
</div>
)
}
}
export default App4;
'Stack > React' 카테고리의 다른 글
[React] React Component Styling (0) | 2022.06.23 |
---|---|
[React] to-do list (0) | 2022.06.22 |
[React] event-react(Event / ref) (0) | 2022.06.21 |
[React] 컴포넌트 (0) | 2022.06.20 |
[React] 안녕 ~ React (0) | 2022.06.20 |