[React] 8. react-hooks(useState, useEffect, useRef)

dev·2020년 10월 20일
1

React

목록 보기
8/21
post-thumbnail

Hooks 는 React 16.8 에서 추가 되었습니다.
기존에는 함수형 컴포넌트에서 상태를 관리하기 위해서는 클래스 컴포넌트 다시 작성해야 했던 반면에, Hooks가 나오면서 함수형 컴포넌트에서도 상태를 가질 수 있게 되었습니다. Hooks는 이것 외에도 다양한 기능들을 제공합니다.
함수형 컴포넌트에서 상태를 가질 수 있게 해주다보니 클래스형 컴포넌트보다 함수형 컴포넌트를 더 많이 사용하고 있습니다.
그러나 Hooks를 도입한다고 해서 이전에 배웠던 리액트에 대한 개념들이 필요 없어지거나 하지는 않습니다. Hooks는 우리가 이미 알고 있던 props, state, context, refs, lifecycle 등에 대해서 더 직접적인 API를 제공해줄 뿐입니다.

즉, Hooks 는 class 를 이용하지 않고 state 와 다른 React 기능들을 사용할수 있게 합니다.

다음 아래 공식 문서를 참조하기바랍니다.
https://reactjs.org/docs/hooks-intro.html

Hooks Api

다음으로 Hooks Api들을 살펴보겠습니다.

1. useState

useState는 함수형 컴포넌트에서 state를 가질 수 있게 하는 Hook입니다.

const [state, setState] = useState(initialState);

useState는 두 개의 요소가 담긴 배열을 반환합니다. 첫 번째 요소는 컴포넌트의 현재 상태이고 두 번째 요소는 상태를 설정할 수 있는 함수입니다.
그리고 useState의 인자는 상태의 초기값을 나타냅니다.
초기값을 설정해주는거기 때문에 처음 랜더링을하고나서 이후에는 인자를 무시합니다.

function App() {
// useState를 사용하여 count라는 state를 생성 초기값은 0으로
  const [count, setCount] = useState(0);
  const add = () => {setCount(count+1);}//setCount로 state값 변경
  const min = () => {setCount(count-1);}
  return (
    <div>
      <p>Current COUNT : {count}</p>
  	  <button onClick={add}>+</button>
      <button onClick={min}>-</button>
    </div>
  );
}

2. useEffect

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

function App() {
  const [count, setCount] = useState(0);
  const add = () => {setCount(count+1);}
  const min = () => {setCount(count-1);}
  useEffect(() => {
    console.log('마운트 될 때만 실행됩니다.');
  });
  return (
    <div>
      <p>Current COUNT : {count}</p>
  	  <button onClick={add}>+</button>
      <button onClick={min}>-</button>
    </div>
  );
}
export default App;

버튼을 클릭하여 state를 변경했을때 다시 랜더링이되면서 useEffect가 타는걸 볼 수 있습니다.

useEffect를 마운트 될 때만 실행하고 싶을 경우에는 두번째 파라미터에 비어있는 배열을 넣어주면 처음에만 발생하고 그 이후 랜더링이 될 때에는 발생하지 않는걸 확인할 수 있습니다.

useEffect(() => {
console.log('랜더링~');
},[]);

그리고 특정 값이 없데이트 될 때만 실행 하고 싶을 때는 두번째 파라미터에 [특정값]을 넣어주면 됩니다.

3. useRef

useRef 를 사용하여 ref 를 설정하면, useRef 를 통해 만든 객체 안의 current 값이 실제 엘리먼트를 가르키게 됩니다
이벤트를 발생했을 때 e.target.value로 해당 값을 가져오는 방법을 useRef를 사용하여 값을 가져 올 수 있습니다.

function App() {
  const textRef = useRef();
  const changeE = (e)=>{
    let eValue = e.target.value;
    let refValue = textRef.current.value;
    console.log(eValue,refValue);
  }
  return (
    <div>
      <input type = "text" ref= {textRef} onChange = {changeE}></input>
    </div>
  );
}
export default App;

textbox에 입력을 했을때 개발자도구 console창에 동일하게 값이 나오는 걸 볼 수 있습니다.

이 3가지의 hooksApi를 사용하여 text를 입력받아 추가를 하면 목록에 추가되면서 카운팅이 되고, 목록에 추가된 데이터를 클릭 시 카운팅이 감소되는 예제를 만들어보겠습니다.파일은 총 App, Header, List, Item, Item.css 총 5개 파일을 사용할 것입니다.

Item.css
Item.css파일을 만듭니다.
용도는 화면에 할일을 추가한 목록 js공부, react을 클릭 시 변화를 주기 위함입니다.

.done {
text-decoration: line-through;
font-style: italic;
}

App.js

import List from './List.jsx';
import React, { Component, useState, useEffect } from 'react';
import Header from './Header.jsx';
import Form from './Form.jsx';
export const TodoContext = React.createContext();
const App = () => {
  //useState를 사용하여 state 생성, 초기값 지정
  const [state, setState] = useState([
    {"id" :"js공부", "status" : "re"},
    {"id" :"react", "status" : "re"}]); 
  const[newTodo, setNewTodo] = useState();//useState를 사용하여 newTodo 생성 초기값 없음
  const changeInputData = (e) =>{ // onChange 이벤트 발생 시 NewTodo에 해당 값 저장
    setNewTodo(e.target.value);
  }
  const addTodo = (e) => {  // onClick 이벤트 발생 시 state에 해당 값 저장
    e.preventDefault();
    setState([...state, {id : newTodo, status : 're'}]);
  }
  const changeT = (id) => { // 할 일 목록 내 item을 클릭 시 발생하는 이벤트 클릭 시 해당 값에 변화를 주기 위함
    const updateT = state.map(todo =>{
      if(todo.id === id){
        if(todo.status === 'done') todo.status= 're';
        else todo.status = 'done';
      }
      else{
      }
      return todo; 
    });
    setState(updateT);
 }
 useEffect( () =>{  //랜더링 될 때 호출
    console.log('새로운 내용이 랜더링됐네요', state);
   }, [state]); // 특정값 state에 지정하였기 때문에 newTodo가 변경될때는 타지 않음
  return (
    <>
      <Header state = {state}></Header>
      <form action="">
        <input type="text" name="" onChange={changeInputData} />
        <button onClick={addTodo}>할일추가</button>
      </form>
      <List todos= {state} changeT = {changeT}></List>
    </>
  )
}
export default App;

Header.jsx
여기에서는 할 일 목록 갯수를 보여줍니다.
filter() 함수를 사용하여 인자값으로 넘어온 stat의 status값이 "re"인 것만 카운팅 하여 보여줍니다.

import React, { useMemo } from "react";
import { TodoContext } from "./App.js";
const Header = ({ state }) => {
  const count = (state) => {
    let cnt = state.filter((v) => v.status === "re").length;
    return cnt;
  };
  return (
    <div>
      <h1>Hooks를 사용한 예제</h1>
      <div>갯 수 : {count(state)}개</div>
    </div>
  );
};
export default Header;

List.jsx
여기에서는 할 일 목록을 보여줍니다.
map() 함수를 사용하여 상위 컴포넌트에서 전달받은 인자값을 item에게 넘겨줍니다.

import Item from "./Item.jsx";
import React, { useContext } from "react";
import { TodoContext } from "./App.js";
const List = ({ todos, changeT }) => {
  let todoList = todos.map((todo) => (
    <Item todo={todo} changeT={changeT}></Item>
  ));
  return (
    <div>
      <ul>할 일 목록{todoList}</ul>
    </div>
  );
};
export default List;

item.jsx
여기에서는 인자값으로 받은 todo에 status값을 확인하여 css를 변화를 줄 수 있게 해줍니다.

import "./item.css";
const Item = ({ todo, changeT }) => {
  const toggleItem = (e) => {
    const id = e.target.dataset.id;
    changeT(id);
  };
  let classNm = "";
  // status가 "done"인 경우 css를 입힐 수 있게 값을 저장합니다.
  if (todo.status === "done") {
    classNm = "done";
  } else {
    classNm = "";
  }
  return (
    <div>
      <li data-id={todo.id} className={classNm} onClick={toggleItem}>
        {todo.id}
      </li>
    </div>
  );
};
export default Item;

이렇게 코드를 작성한 후 실행하여
hooks를 입력하고 할일추가버튼을 클릭하면
할 일 목록에 hooks가 추가가되고, 갯수가 증가하는 걸 확인 할 수 있습니다.
또 hooks를 클릭하였을 경우
hooks에 줄이 쳐지는 css가 정상 적용되며 갯 수가 줄어드는 걸 확인할 수 있습니다.

3가지 hooksAPI를 사용하여 예제를 만들어보았습니다.
다음에는 나머지 API를 보도록 하겠습니다.

profile
studying

0개의 댓글