UseEffect - 사이드 이펙트를 사용할 때 쓰는 훅
매개변수 : setup 함수, [] 배열
생략 -> 항상 호출됨
빈배열 -> 최초 마운트 시에 호출된다.
지정값이 들어간 배열 -> 해당 값이 변경된 경우에만 setup함수 호출
reduce 메서드
reducer
reducer가 한번 호출될때마다 다음번 매개변수에 마지막 리턴값을 전달한다.
state가 다음번 useReducer 될 때 업데이트 되는 것이다!
예제 1. 은행 (입금 /출금) 프로그램
import { useState } from "react";
import { useReducer } from "react";
import Button from "./Button";
const reducer = (state, action) => {
switch(action.type){
case 'DEPOSIT':
return state + action.payload;
case 'WITHDRAW' :
return state - action.payload;
default :
return state;
}
};
function Account() {
const [money, setMoney] = useState('');
const [account, dispatch] = useReducer(reducer, 0);
//dispatch 함수를 호출하여, 해당 함수를 사용할 수 있는 것이다.
//reducer은 작업을 진행할 함수이다.
const depositDown = () =>{
dispatch({type: 'DEPOSIT', payload: money});
}
const withdrawDown = () =>{
dispatch({type: 'WITHDRAW', payload: money});
}
return(
<>
<p>잔고 : {account}</p>
<input type="text" onChange={(e)=>setMoney(parseInt(e.target.value))} />
<Button onClick = {depositDown} value = '예금' />
<Button onClick = {withdrawDown} value = '출금' />
</>
);
}
export default Account;
useReducer 작성법!
1. const [account, dispatch] = useReducer(reducer, 0);
- account : 현재 state 상태를 나타낸다. reducer 함수에 자동으로 전달됨 (reducer이 돌면서 업데이트 된다. )
- dispatch : reducer을 작동시키는 함수? 라고 이해함
- reducer 실제 행동을 취하는 함수! 그렇기 때문에 (state, action) 을 인자로 받는다.
action에는 객체를 전달하는데, type을 주로 전달하여
switch문을 작성한다.
switch(action.type){
case ~~~ :
}
useRef : 값을 관리는 하지만, 값이 변경되어도 리렌더링을 하지 않음! => 불필요한 호출 줄인다.
값에 접근할 때 : current를 붙인다.
매개변수 : 초기값
용법1. 불필요한 렌더링을 방지한다 : 렌더링이필요하여 useState로 변경했던 것들을 useRef로 변경해주면 렌더링이 일어나지 않고 값만 관리한다!
<input type="number" style={{ width: '40px' }} defaultValue="1" //ref를 쓸 때에는 defaultValue로 지정 필요
onChange={e => num.current = Number(e.target.value) } />
defaultValue으로 초깃값을 주어야한다!!
num,current에다가 타겟값을 넣어주고 값을 꺼내주는 것이다. (리렌더링x)
용법 2. dom 객체를 직접 접근할일이 있을 때 document의 queryselector를 쓰지 않고 useRef를 쓰면 된다.
import { useRef, useState } from "react";
import PropTypes from 'prop-types';
function TodoInput({ addItem }){
const [title, setTitle] = useState('');
const titleElem = useRef();
const handleAdd = () => {
if(title.trim() !== ''){
const item = { title };
addItem(item);
setTitle('');
titleElem.current.focus();
}
};
const handleKeyUp = event => {
if(event.key === 'Enter') handleAdd();
};
return (
<div className="todoinput">
<input ref={ titleElem } type="text" value={ title } onChange={ event => setTitle(event.target.value) } onKeyUp={ handleKeyUp } autoFocus />
<button type="button" onClick={ handleAdd }>추가</button>
</div>
);
}
TodoInput.propTypes = {
addItem: PropTypes.func
};
export default TodoInput;
예제 1. 은행 프로그램에 input 요소를 useRef 로 변경하기 ! => 왜냐하면 렌더링이 필요 없는 값이기 때문에!!!
사실상 input요소 안의 money 값은 버튼이 클릭되었을 때만 렌더링하면 된다. 그렇기 때문에~ 한번 useRef 로 작성해보자
import { useState } from "react";
import { useReducer, useRef } from "react";
import Button from "./Button";
const reducer = (state, action) => {
switch(action.type){
case 'DEPOSIT':
return state + action.payload;
case 'WITHDRAW' :
return state - action.payload;
default :
return state;
}
};
function Account() {
// const [money, setMoney] = useState('');
// useRef 를 사용해서 작성해보자!
const money = useRef(0);
const [account, dispatch] = useReducer(reducer, 0);
//dispatch 함수를 호출하여, 해당 함수를 사용할 수 있는 것이다.
//reducer은 작업을 진행할 함수이다.
const depositDown = () =>{
dispatch({type: 'DEPOSIT', payload: money.current});
}
const withdrawDown = () =>{
dispatch({type: 'WITHDRAW', payload: money.current});
}
return(
<>
<p>잔고 : {account}</p>
<input type="text" defaultValue="0" onChange={(e) => {money.current = Number(e.target.value)
console.log(money.current)}} />
<Button onClick = {depositDown} value = '예금' />
<Button onClick = {withdrawDown} value = '출금' />
</>
);
}
export default Account;
useRef 작성 방법
1. const money = useRef(0)
- money였던 input은 렌더링하지 않겠다는 뜻이다. 초기값은 0이다.
- 값에 접근하기 위해서는 무조건 .current로 접근한다!!!
- 따라서, onChange 함수에서 정의할 때에는 input 값의 value를 current 값으로 넣어주는 코드를 실행해야한다.
(e) => {
money.current = e.target.value;
}
< 만약 DOM 객체라면? - focus 예제>
1. const dom = useRef('') //초기화를 해주고,
2. focus의 주체가되는 태그 속성에 ref 를 추가한다.
<input ref = {dom} ... />
3. click 태그의 handle 함수에 focus를 정의한다.
dom.current.focus();