ReactJS - Hooks

ROCKBELL·2022년 12월 6일
0

리액트

목록 보기
10/12

useState

const [value, setValue] = useState(0);

  • 함수 파라미터 - 기본값
  • 배열 첫번째 요소 - 상태값
  • 배열 두번째 요소 - 상태를 설정하는 함수

useEffect

리액트 컴포넌트가 랜더링될때마다 특정 작업을 수행하는 Hook

 const info = () => {
   const [name, setName] = useState('');
   
   useEffect(() => {
   		console.log('렌더링 완료') 
   });
   
   const onChangeName = (e) => {
   	setName(e.target.value);
   }
  
   render(
   	<input value={name} onChange={onChangeName} />
   )
 }
 
 
  • 마운트될 때만 실행 (처음 렌더링될때만 실행)
   // useEffect의 두번째 파라미터로 빈 배열을 넣음
   useEffect(() => {
   		console.log('마운트 될때만 실행')
   }, []);
 
  • 특정 값이 없데이트 될때 실행
   // useEffect의 두번째 파라미터에 값을 배열 요소로 추가
   useEffect(() => {
   		console.log(`${name} 업데이트 될때만 실행`)
   }, [name]);
 
  • 언마운트될때 실행
   useEffect(() => {
   		console.log('마운트')
     return () => {
     	console.log('언마운트')
     }
   }, []);
  

useReducer

리듀서는 현재 상태, 그리고 업데이트를 위해 필요한 정보를 담은 액션 값을 전달 받아 새로운 상태를 반환하는 함수

function reducer(state, action) {
	return {...} // 불변성을 지키면서 업데이트한 새로운 상태를 반환
}

function reducer(state, action) {
	switch(action.type) {
      case 'INCREMENT':
        return { value : state.value + 1}
      case 'DECREMENT':
        return { value : state.value - 1}
      default:
        return state;
    }
}

const Counter = () => {
	const [state, dispatch] = useReducer(reducer, {value : 0});
  
   return (
   	 <div>
       <p>count : {state.value} </p>
       <button onClick={()=>dispatch({type : 'INCREMENT'})}>+ 1</button>
       <button onClick={()=>dispatch({type : 'DECREMENT'})}>- 1</button>
     </div>
   );
}

useMemo

컴포넌트 내부에서 발생하는 연산을 최적화하는 Hook
렌더링 과정에서 특정 값이 바뀌었을 때만 연산을 실해하고, 값이 바뀌지 않았다면 이전에 연산했던 결과를 다시 사용하는 방식

const getAverage = numbers => {
  if(numbers.length === 0) return 0;
  const sum = numbers.reduce((acc, cur) => acc + cur);
  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('');
  }
  
  // list가 바뀌었을 때만 연산
  const avg = useMemo(()=> getAverage(list), [list])
  
  return(
  	...
  )
}

useCallback

렌더링 성능 최적화를 위해 함수를 재사용하는 Hook

 
const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');
  
  // 컴포넌트가 처음 렌더링 될때 만 함수 생성
  const onChange = useCallback((e) => {
  	setNumber(e.target.value);
  }, [])
  
  // number 혹은 lsit가 바뀌었을 때만 함수 생성
  const onInsert = useCallback((e) => {
  	const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
  }, [number, list])
  
  const avg = useMemo(()=> getAverage(list), [list])
  
  return(
  	...
  )
}

useRef

함수형 컴포넌트에서 ref를 쉽게 사용할수 있는 Hook

const Average = () => {
  const [list, setList] = useState([]);
  const [number, setNumber] = useState('');
  const inputEl = useRef(null);
  
  const onChange = useCallback((e) => {
  	setNumber(e.target.value);
  }, [])
  
  const onInsert = useCallback((e) => {
  	const nextList = list.concat(parseInt(number));
    setList(nextList);
    setNumber('');
    // inputEl 요소로 focus 이동
    inputEl.current.focus();
  }, [number, list])
  
  const avg = useMemo(()=> getAverage(list), [list])
  
  return(
  	<div>
   		<input value={number} onChange={onChange} ref={inputEl}>
          <button onClick={onInsert}>등록</button>
          <ul>
            {list.map((value, index)=>{
            	<li key={index}>{value}</li>
            })}
          </ul>
          <p>평균값 : {avg}</p>
    </div>
  )
  • 로컬변수 사용 (렌더링과 관련되지 않은 값 관리)

 const RefSample = () => {
   const id = useRef(1);
   const setId = (n) => {
   	id.current = n;
   }
   const printId = () =>  console.log(id.current);
   
   return(
   ...
   )
 }

Custom Hooks

비슷한 기능을 공유하는 경우 Custom Hook을 작성하여 재사용 가능

// useInputs.js
 import {useReducer} from 'react';

 function reducer(state, action) {
 	return {
    	...state,
      	[action.name] : action.value
    }
 }

 export default function useInputs(initailForm) {
 	const [state, dispatch] = useReducer(reducer, initailForm);
   
   const onChange = (e) => {
   	  dispatch(e.target)
   };
   
   return [state, onChange];
 }
import useInputs from './useInputs'

const Info = () => {
	const [state, onChange] = useInputs({
  		name : '',
        nickname : ''
    })
    
    const {name, nickname} = state;
  
  return(
  	<div>
      <input name="name" value={name} onChange={onChange}>
      <input name="name" value={nickname} onChange={onChange}>
      <div>
        이름 - {name} (닉네임 - {nickname})
      </div>
    </div>
  )
}
profile
luv it

0개의 댓글