
함수형 컴포넌트에서도
useState를 이용해 하나의 상태를 관리하기 위해선..?
⇒ 하나의 상태에 useState 를 이용함
useState를 이용해 여러개의 상태를 관리하기 위해선..?
⇒ useState를 여러번 사용하면 된다.
useEffect는 컴포넌트가 렌더링 될 때마다 특정 작업을 수행할수 있도록 해준다.
useEffect(()=> {
해당 함수
},[]);
useEffect(()=> {
해당 함수(특정값)
},[특정값]);

useEffect는 기본적으로 랜더링되고 난 직후
하지만, 컴포넌트가 언마운트되기 전이나, 업데이트되기 직전에 어떤 작업을 수행하고 싶다면?
⇒ 뒷정리 함수를 반환해야한다
Info.js
import { render } from '@testing-library/react';
import React, { useState, useEffect } from 'react'
function Info() {
const [name, setName] = useState('');
const [nickName, setNickName] = useState('');
useEffect(() => {
console.log('effect')
console.log(name);
return () => {
console.log('clean up'); // 컴포넌트가 언마운트 되기전(즉 APP.js에 조건에 의해서 컴포넌트가 닫힐때 나옴)
console.log(name);
};
}, [name])
const onChangeName = e => {
setName(e.target.value);
};
const onChangeNickName = e => {
setNickName(e.target.value);
};
return (
<div>
<div>
<input
value={name}
onChange={onChangeName}
/>
<input
value={nickName}
onChange={onChangeNickName}
/>
</div>
<div>
<div>
<b>이름:</b> {name}
</div>
<div>
<b>닉네임:</b> {nickName}
</div>
</div>
</div>
)
}
export default Info
App.js
function App() {
const [visible, setvisible] = useState(false)
return (
<div>
<button
onClick={() => {
setvisible(!visible);
}}
>
{visible ? '숨기기' : '보이기'}
</button>
<hr />
{visible && <Info />} // 조건에 따라 컴포넌트가 마운트 , 언마운트 된다
</div>
);
}
export default App;
useState보다 더 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 설정 가능
리덕스라는 개념에서 나온다
⇒ 불변성 유지
function reuducer(state, action){
return { ...} // 새로운 상태
{
type: 'INCREMENT", // 다른 값이 필요하면 추가로 들어간다.
}
import React, { useReducer } from 'react'
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { value: state.value + 1 };
case 'DECREMENT':
return { value: state.value - 1 };
default:
return state;
}
}
// 리듀서 함수를 만들어서 dispatch 함수로 받아오는 인자를
function Counter() {
const [state, dispatch] = useReducer(reducer, { value: 0 });
return (
<div>
<p>
현재 카운터 값은 <b>{state.value}</b>
</p>
<button onClick={() => dispatch({ type: 'INCREMENT' })}> +1</button>
<button onClick={() => dispatch({ type: 'DECREMENT' })}> +1</button>
</div>
)
}
export default Counter
useState랑 비슷하지만, 인자에 따라 설정을 바꿀수 있다 생각하자
기존에는 인풋이 여러개여서 useState를 여러개 사용했는데
⇒ useReducer을 이용하면 기존 클래스형 컴포넌트에서 했던것 처럼 e.target안에 프로퍼티에 따라 여러개를 사용할 필요가 없다
import { render } from '@testing-library/react';
import React, { useState, useEffect, useReducer } from 'react'
function reducer(state, action) {
return {
...state,
[action.name]: action.value
} // 스프레드 문법을 이용해서 기존 stata를 가져오고 , e.target = action으로 줘서 값에 따라 값을 새로 생성한다
}
function Info() {
const [state, dispatch] = useReducer(reducer, {
name: '',
nickName: ''
}) // 초기 state 값을 설정해주고
const { name, nickName } = state;
const onChange = e => {
dispatch(e.target); // action 값을 dispatch로 보냄
}
return (
<div>
<div>
<input
name="name" // e.target.name
value={name} // e.target.value
onChange={onChange}
/>
<input
name="nickName"
value={nickName}
onChange={onChange}
/>
</div>
<div>
<div>
<b>이름:</b> {name}
</div>
<div>
<b>닉네임:</b> {nickName}
</div>
</div>
</div>
)
}
export default Info
함수형 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있다
해당 하는 값의 결과가 useMemo에서 실행되지 않는다면, 결과또한 바뀌지 않는다
이해하기 쉽게 생각한다면
useEffect는 해당 함수의 인자를, 두번째 파라미터로 받으면, 해당 인자가 변경될때만 마운트(랜더링) 된다
useMemo또한 해당 함수의 인자를, 두번째 파라미터로 받으면 useMemo의 리턴값은 해당 함수의 인자가 변경 될때만 변경된다
import React, { useState } from 'react';
const getAverage = numbers => {
console.log('평균값 계산 중..');
if (numbers.length === 0) return 0;
const sum = numbers.reduce((a, b) => a + b);
return sum / numbers.length;
};
const Average = () => {
const [list, setList] = useState([]);
const [number, setNumber] = useState("");
const onChange = e => {
setNumber(e.target.value);
};
const onInsert = e => {
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber("");
};
return (
<div>
<input value={number} onChange={onChange} />
<button onClick={onInsert}>등록</button>
<ul>
{list.map((value, index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b> {getAverage(list)}
</div>
</div>
);
};
export default Average;
export default Average
이제 list 배열의 내용이 바뀔 때만 getAverage 함수가 호출됩니다.
주로 렌더링 성능을 최적화해야 하는 상황에서 사용된다.
함수또한 랜더링 될때마다 새로 호출 되는데
해당 함수가 만약 함수 내부가 변경되거나 새로 호출 받는게 아니라면
한번만 랜더링하고 계속 사용하는것이 성능에 좋다
함수선언을 useCallback으로 해주면 된다
const onChang = useCallback(e=>{
setNumber(e.target.value)
},[]);
함수형 컴포넌트에서 ref를 쉽게 사용할수 있도록 해준다
useRef를 이용하면, this 처럼 로컬 변수를 사용할수 있게된다.
로직을 파일로 따로 만들어 분리 한뒤에
불러와서 쓰면된다.