useState: 가장 기본적인 hook로 함수 컴포넌트에서도 가변적인 상태를 지닐 수 있게한다.
import { 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>
<div>
<input name="name" value={number} onChange={onChange}/>
<button onClick={onInsert}>등록</button>
</div>
<ul>
{list.map((value,index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b>{getAverage(list)}
</div>
</div>
);
}
export default Average;
input 내용이 바뀔 때 마다 getAverage가 호출된다
useEffect: 리액트 컴포넌트가 랜더링 될 때마다 특정 작업을 수행하도록 설정할 수 있게한다
(componentDidMount+componentDidUpdate 형태)
import { useState, useEffect } from 'react';
const Info = () =>{
const [name, setName] = useState('');
const [nickname ,setNickName] = useState('');
useEffect (() => {
console.log('렌더링 완료됬습니다');
console.log({
name, nickname
});
//console.log('마운트 될 때만 실행');
});
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>
<b>이름:</b>{name}
<b>닉네임:</b>{nickname}
</div>
</div>
);
};
export default Info;
useEffect (() => {
//console.log('렌더링 완료됬습니다');
//console.log({
//name, nickname
//});
console.log('마운트 될 때만 실행');
}, []);
useEffect을 이렇게 바꾸면 마운트 될 때만 console에 찍힌다
useEffect (() => {
//console.log('렌더링 완료됬습니다');
//console.log({
//name, nickname
//});
console.log(name);
}, [name]);
name 업데이트 될 때만 실행
useEffect (() => {
//console.log('렌더링 완료됬습니다');
//console.log({
//name, nickname
//});
console.log('effect');
return () =>{
console.log('cleanup');
console.log(name);
};
}, [name]);
import { useState } from 'react';
const App = () =>{
const [visible, setVisible] = useState(false);
return(
<div>
<button
onClick={() =>
{setVisible(!visible)}
}
>
{visible ? '숨기기': '보이기'}
</button>
<hr/>
{visible && <Info/>}
</div>
);
숨길때 name과 nickName이 초기화되며 그 전에 데이터가 콘솔에 나타난다
useReducer: 다양한 컴포넌트 상황에 따라 다양한 상태를 다른 값으로 업데이트해 주고 싶을 때 사용
현재 상태, 업데이트를 위해 필요한 정보를 담은 액션 값을 전달받아 새로운 상태를 반환하는 함수
import { useReducer } from 'react';
function render(state, action){
switch (action.type){
case 'INCREMENT':
return { value: state.value +1 };
case 'DECRMENT':
return { value: state.value -1 };
default:
return state;
}
}
const Counter2 =() =>{
const [state, disPatch]= useReducer(render, {value:0});
return(
<div>
<p>
현재 카운터 값은 <b>{state.value}</b>
</p>
<button onClick={()=> disPatch({ type: 'INCREMENT'})}>+1</button>
<button onClick={()=> disPatch({ type: 'DECRMENT'})}>-1</button>
</div>
);
};
export default Counter2;
import { useReducer } from 'react';
function render(state, action){
return{
...state,
[action.name]: action.value
};
}
const Info2 =() =>{
const [state, disPatch]= useReducer(render, {name:'', nickName:''});
const {name, nickName} =state;
const onChange = e => {
disPatch(e.target);
};
return(
<div>
<div>
<input name="name" value={name} onChange={onChange}/>
<input name="nickName" value={nickName} onChange={onChange}/>
</div>
<div>
<b>이름:</b>{name}
<b>닉네임:</b>{nickName}
</div>
</div>
);
};
export default Info2;
useMemo: 함수 컴포넌트 내부에서 발생하는 연산을 최적화할 수 있다
import { useState, useMemo } 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('');
};
const avg = useMemo(()=> getAverage(list), [list]);
return(
<div>
<div>
<input name="name" value={number} onChange={onChange}/>
<button onClick={onInsert}>등록</button>
</div>
<ul>
{list.map((value,index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b>{avg}
</div>
</div>
);
}
export default Average;
list 배열의 내용이 바뀔 때만 getAverage 함수가 호출된다
useCallback: 렌더링 성능을 최적화 할 때 사용
import { useState, useMemo, useCallback } 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 = useCallback(e =>{
setNumber(e.target.value);
}, []);
const onInsert = useCallback(e =>{
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
}, [number,list]);
const avg = useMemo(()=> getAverage(list), [list]);
return(
<div>
<div>
<input name="name" value={number} onChange={onChange}/>
<button onClick={onInsert}>등록</button>
</div>
<ul>
{list.map((value,index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b>{avg}
</div>
</div>
);
}
export default Average;
첫 렌더에만 함수 생성, number와 list가 바꼈을 때만 함수 생성
useRef: ref를 쉽게 사용할 수 있도록 한다
import { useState, useMemo, useCallback, useRef } 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 inputEI =useRef(null);
const onChange = useCallback(e =>{
setNumber(e.target.value);
}, []);
const onInsert = useCallback(e =>{
const nextList = list.concat(parseInt(number));
setList(nextList);
setNumber('');
inputEI.current.focus();
}, [number,list]);
const avg = useMemo(()=> getAverage(list), [list]);
return(
<div>
<div>
<input name="name" value={number} onChange={onChange}/>
<button onClick={onInsert}>등록</button>
</div>
<ul>
{list.map((value,index) => (
<li key={index}>{value}</li>
))}
</ul>
<div>
<b>평균값:</b>{avg}
</div>
</div>
);
}
export default Average;
current값이 실제 엘리먼트를 가리킴
ref 안에 값이 바뀌어도 렌더링 되지 않는다
커스텀 Hooks 만들기
import { useReducer } from 'react';
function Reducer(state, action){
return{
...state,
[action.name]: action.value
};
}
export default function useInputs(initialForm){
const [state,disPatch]= useReducer(Reducer, initialForm);
const onChange = e =>{
disPatch(e.target);
};
return [state, onChange];
}
//import { useReducer } from 'react';
import useInput from "./useInput";
const Info2 =() =>{
const [state, onChange]= useInput({name:'', nickName:''});
const {name, nickName} =state;
return(
<div>
<div>
<input name="name" value={name} onChange={onChange}/>
<input name="nickName" value={nickName} onChange={onChange}/>
</div>
<div>
<b>이름:</b>{name}
<b>닉네임:</b>{nickName}
</div>
</div>
);
};
export default Info2;
'Web > React & Next.js' 카테고리의 다른 글
react 아이콘 넣기 (0) | 2022.04.12 |
---|---|
컴포넌트 스타일링 (0) | 2022.04.06 |
컴포넌트의 라이프사이클 메서드 (0) | 2022.04.05 |
컴포넌트 반복 (0) | 2022.04.04 |
DOM에 이름 달기 (0) | 2022.04.03 |