'useReducer'에 해당되는 글 1건

8. React Hooks 란?

react 2020. 2. 3. 11:58

Hooks 란 ?

 

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

즉 클래스 형태에서 리액트를 구현 한던걸 함수 방식으로도 구현이 가능 하도록 해준게 hooks 라는 말 같다.

 

이제 부터 hooks 기능을 설명 하나씩 살펴 보겠습니다.

 

  • useState : 가장 기존적인 hook 이며 컴포넌에서 상태 관리를 해야 한다면 이 hook를 사용 하면 됨.
import React from "react";

const Counter = () => {
  const [value, setValue] = useState(0); // 0으로 초기화

  return (
    <div>
      <p>
        현재 카운터 값은 <b>{value}</b> 입니다.
      </p>
      <button onClick={() => setValue(value + 1)}>+1</button>
      <button onClick={() => setValue(value - 1)}>-1</button>
    </div>
  );
};

value : 상태값
setValue : 상태를 설정하는 함수
useState 첫번째 값은 상태값 두번째 원소는 상태를 설정 하는 함수를 뜻한다.

  •  useEffect : 컴포넌트 렌더링이 될떄 마다 특정 작업을 수행 할수 있도록 설정 하는 hook 클래스형에서는 componentDidMount,componentDidupdate를 합친 형태랑 비슷 하다.
import React, { useState, useEffect } from "react";

const Info = () => {
  const [name, setName] = useState("");
  const [nickname, setNickname] = useState("");

  useEffect(() => {
    console.log("렌더링 완료");
    console.log({
      console.log(nickname);
      console.log(name);
    });
     return () => { //리턴을 사용 하게 되면 해당 렌더링 숨김 할때 실행 된다.
      console.log("cleaup");
      console.log(name);
    };
  },[]); // []를 사용 하게 되면 인풋창이 업데이트시 매번 실행 됐던게 처음 렌더링 시점에 실행된다.
  //그리고 처음 렌더링 시점이 아니고 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>
  );
};

값이 다 변경 되고 페이지 변경이 완료되는 시점에 useEffect 함수가 실행 된다.
  • useReducer : useSate 보다 다양한 컴포넌트 상황에 따라 값을 업데이트 해주고 싶을떄 사용 하는 hook useState 는 값이 변경 될떄만 사용 하지만 useReducer 파라미터 값을 넘겨줘서 조건문을 넣어서 사용 할수 있다. 예시를 보면 알수 있을것이다.
import React, { useReducer } from "react";

function reducer(state, action) {
  console.log(state);
  switch (action.type) { //type 를 받아서 조건을 나눠서 처리가 가능 하다.
    case "INCREMENT":
      return { value: state.value + 1 };
    case "DECREMENT":
      return { value: state.value - 1 };
    default:
      return false;
  }
}

const Counter = () => {
  const [state, setValue] = useReducer(reducer, { value: 0 }); 
  // useReducer 함수 첫번째 소요에 실행된 함수를 넣어 준다.

  return (
    <div>
      <p>
        현재 카운터 값은 <b>{state.value}</b> 입니다.
      </p>
      <button onClick={() => setValue({ type: "INCREMENT" })}>+1</button>
      //INCREMENT 조건에는 +1을해주고 있다.
      <button onClick={() => setValue({ type: "DECREMENT" })}>-1</button>
      //DECREMENT 조건에는 -1을해주고 있다.
    </div>
  );
};


useReducer을 통해 input 상택 값을 조절 할수도 있다.  input 이 여러개 일때 하나로 사용 가능하다. 

예시를 보는게 이해에 도움이 될듯 하다. 

import React, { useReducer } from "react";

function reducer(state, action) {
  console.log({
    ...state, //name: state.name,nickname: state.nickname 같은 의미
    [action.name]: action.value
  });

  return {
    ...state //name: state.name,nickname: state.nickname 같은 의미
    [action.name]: action.value
  };
}

const Info = () => {
  const [state, dispatch] = useReducer(reducer, {
    name: "",
    nickname: ""
  });
 
  const { name, nickname } = state;// name, nickname 을 state 오르젝트에 담아서 하나로 사용.
  const onChange = e => {
    dispatch(e.target);
    //input을 통으로 넘겨 준다. 이걸로 인해 input 여러가지 일때도 하나로 재활용이 가능.    
  };

  return (
    <div>
      <div>
        <input name="name" value={name} 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 : 컴포넌트 내부에서 발생 하는 연상을 최적화 할수 있다. 

아래 예시는 useMemo 를 사용 하지 않았을때 이렇게 사용 하면 input 값이 입력 될때마다 getAverage 실행된다.

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 nexList = list.concat(parseInt(number));
    setList(nexList);
    setNumber("");
  };

  return (
    <div>
      <input value={number} onChange={onChange} />
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <b>평균값:</b>
      {getAverage(list)}
    </div>
  );
};

export default Average;

useMemo 적용 한 예시 적용을 하게 되면 input 에 입력 될시 마다 아니고 값이 새롭게 입력 될떄만 작동하게 됩니다.

이렇게 하게되면 리렌더를 방지 할수있고 효율이 좋아 진다고 생각 하면 될듯 하다.

import React, { 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 onChange = useCallback(e => {
    setNumber(e.target.value);
  }, []);

  const onInsert = useCallback(
    e => {
      const nexList = list.concat(parseInt(number));
      setList(nexList);
      setNumber("");
    },
    [number, list] 
  );

  const avg = useMemo(() => getAverage(list), [list]);  //리스트가 변경 될떄만 실행
  
  return (
    <div>
      <input value={number} onChange={onChange}/>
      <button onClick={onInsert}>등록</button>
      <ul>
        {list.map((value, index) => (
          <li key={index}>{value}</li>
        ))}
      </ul>
      <b>평균값:</b>
      {avg}
    </div>    
  );
};
  • useRef : 컴포넌트에서 ref를 쉽게 사용 할 수 있도록 해주는 hook
import React, { 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 inputEl = useRef(null); //ref 초기값

  const onChange = useCallback(e => {
    setNumber(e.target.value);
  }, []);

  const onInsert = useCallback(
    e => {
      const nexList = list.concat(parseInt(number));
      setList(nexList);
      setNumber("");
      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>
      <b>평균값:</b>
      {avg}
    </div>
  );
};

export default Average;

간략하게 hooks 기능들을 살펴 봤다 더 자세한 자료를 원한다면 참고 자료 링크를 공유 할테니 참고 해주시면 됩니다.

 

참고 링크 :

https://nikgraf.github.io/react-hooks/

https://github.com/rehooks/awesome-react-hooks

https://velog.io/@velopert/react-hooks

https://ssangq.netlify.com/posts/react-memo-useMemo-useCallback

https://ko.reactjs.org/docs/hooks-intro.html

'react' 카테고리의 다른 글

7. 라이플 사이클(Life Cycle) 메서드의이해  (0) 2020.01.22
2. JSX 란  (0) 2019.12.03
1. 리액트 시작  (0) 2019.12.03
블로그 이미지

foglove

개인적으로 공부 하면서 이해가 안가는것들 정리 하거나 책을 보면서 정리 해보는 습관을 가지고 시작한 블로그 입니다.

,