React) Hooks 1

iamokian·2022년 3월 24일
0

React

목록 보기
8/10

8. Hooks(1)

Hooks는 리액트 v16.8에 새로 도입된 기능으로 함수컴포넌트에서도 상태 관리를 할 수 있는 useState, 렌더링 직후 작업을 설정하는 useEffect 등의 기능을 제공하여 기존의 함수 컴포넌트에서 할 수 없었던 다양한 작업을 할수 있게 해준다.


8-1. useState

useState는 가장 기본적인 Hook이며, 함수 컴포넌트에서도 가변적인 상태를 지닐 수 있게 해준다.

import React, { useState } from 'react';
//Hook를 쓸때에는 꼭 사용할 훅을 임포트해와야함!

const Counter = () => {
	const [value, setValue] = useState(0);
  	//위 코드는 배열 비구조화 할당으로 배열안의 원소를 새로운 이름으로 가져온것이다.
  	//const useState = [상태값, 상태설정함수]; 이렇게 된 배열을 위와같이 가져온것!
  	//상태값에는 다양한 타입의 값이 들어갈 수 있다.
  
  	return (
    	<div>
      		<p>현재 카운터 값은 <b>{value}</b>입니다.<p>
			<button onClick={() => setValue(value + 1)}>+1</button>
			<button onClick={() => setValue(value - 1)}>-1</button>
      	</div>
    )
}

export default Counter;

useState 함수의 파라미터에는 상태의 기본값을 넣어 준다. 위 코드는 기본값을 0으로 설정한 것이다. 이 함수가 호출되면 배열을 반환하는데, 그 배열의 첫 번째 원소(value)는 상태 값, 두 번째 원소(setValue)는 상태를 설정하는 함수이다. 이 함수에 파라미터를 넣어서 호출하면 전달받은 파라미터로 값이 바뀌고 컴포넌트가 리렌더링 된다.


8-2. useEffect

useEffect는 리액트 컴포넌트가 렌더링 될 때마다 특정 작업을 수행하도록 설정할 수 있는 Hook이다. 클래스형 컴포넌트의 componentDidMount와 componentDidUpdate를 합친 형태로 보아도 무방하다.

import React, { useState, useEffect } from 'react';

const Info = () => {
  	const [name, setName] = useState('');
	const [nickname, setNickname] = useState('');
  
  	ustEffect(() => {
    	console.log('렌더링 완료');
      	console.log({
        	name,
          	nickname
        });
    });
  
  	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}      
            </div>
			<div>
            	<b>닉네임:</b> {nickname} 
            </div>
      	</div>
    )
}

export default Info;

1. 마운트될 때만 실행하고 싶을 때

useEffect에서 설정한 함수를 컴포넌트가 화면에 맨 처음 렌더링 될때만 실행하고, 업데이트될 때는 실행하지 않으려면 함수의 두번 째 파라미터로 비어있는 배열을 넣어주면 된다.

ustEffect(() => {
  console.log('마운트될 때만 실행');
}, []);

2. 특정 값이 업데이트될 때만 실행하고 싶을 때

위와 반대로 특정 값이 변경될 때만 호출하고 싶을 경우에는 useEffect의 두 번째 파라미터로 전달되는 배열 안에 검사하고 싶은 값을 넣어주면 된다. 수정하자면 아래와 같다.

ustEffect(() => {
  console.log(name);
}, [name]);

배열안에는 useState를 통해 관리하고 있는 상태를 넣어 주어도 되고, props로 전달받은 값을 넣어 주어도 된다.


8-3. useMemo

useMemo를 사용하면 함수 컴포넌트 내부에서 발생하는 연산을 최적화 할 수 있다.
예를 들어 평균값을 구하는 코드를 짰을 때, 인풋에 숫자를 등록할 때뿐만 아니라, 인풋내용이 수정될 때도 함수가 호출될 것이다. useMemo Hook를 사용해 이런식의 작업을 최적화할 수 있다. 렌더링 하는 과정에서 특정 값이 바뀌었을 때만 연산을 실행하고, 원하는 값이 바뀌지 않았다면 이전에 연산했던 결과를 다시 사용하는 방식이다.

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 = () => {
      	//배열을 변경해야 할때는 꼭 새로운 배열을 만들어 값을 없데이트시켜주기
    	const nextList = list.concat(parseInt(number));
      	setList(nextList);
      	setNumber('');
    };
  
  	//list값이 업데이트 될때만 실행되게 하기 위해 두번째 파라미터에 [list]를 넣어줌
  	const avg = useMeno(() => getAverage(list), [list]);
  
  	return (
    	<div>
      		<input value={number} onChange={onChange}/>
      		<button onClick={onInsert}>등록</button>
			<ul>
              {list.map((value, index) =>(
                //리액트에서 배열만들때에는 key props는 필수!
                <li key={index}>{value}</li>
              ))}
            </ul>
			<div>
            	<b>평균값:</b> {avg}
            </div>
      	</div>
    );	
};

export default Average;

8-4. useCallback

useCallBack은 useMemo와 비슷한 함수이다. 주로 렌더링성능을 최적화해야 하는 상황에서 사용한다. 이 Hook을 하숑하면 만들어 놨던 함수를 재사용할 수 있다. 위에 만든 onChange와 onInsert함수는 컴포넌트가 리렌더링 될때마다 새로 만들어진 함수를 사용하게 된다. 그것을 최적화 시켜보자.

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('');
  
	//useCallBack를 사용해 최적화! 컴포넌트가 처음 렌더링 될때만 함수 생성
  	const onChange = useCallback(e => {
    	setNumber(e.target.value);
    }, []);
  	
  	//useCallBack를 사용해 최적화! number, list가 바뀌었을 때만 함수 생성
  	const onInsert = useCallback(() => {
    	const nextList = list.concat(parseInt(number));
      	setList(nextList);
      	setNumber('');
    }, [number, list]);
  
  	const avg = useMeno(() => getAverage(list), [list]);
  
  	return (
    	<div>
      		<input value={number} onChange={onChange}/>
      		<button onClick={onInsert}>등록</button>
			<ul>
              {list.map((value, index) =>(
                //리액트에서 배열만들때에는 key props는 필수!
                <li key={index}>{value}</li>
              ))}
            </ul>
			<div>
            	<b>평균값:</b> {avg}
            </div>
      	</div>
    );	
};

export default Average;

useCallback의 첫 번째 파라미터에는 생성하고 싶은 함수를 넣고, 두 번째 파라미터에는 배열을 넣으면 된다. 이 배열에는 어떤 값이 바뀌었을 때 함수를 새로 생성해야 하는지 명시해야 한다. 함수내부에서 상태 값에 의존해야 할 때는 그 값을 반드시 두 번째 파라미터 안에 포함시켜 주어야한다.


리액트를 다루는 기술을 읽고 요약한 글 입니다😊

profile
필기하고 기록하고

0개의 댓글