React Hooks

Goofi·2023년 3월 8일
0
post-custom-banner

React Hooks

React Hooks은 리액트의 새로운 기능으로 React 16.8버전에 새로 추가된 기능이다.

  • 기존 클래스형 컴포넌트 방식과는 다르게 state, component에 대한 것들을 바꿔 놓았다.
  • 함수형 컴포넌트에서 state 가질 수 있게 되었다.
  • react hook을 사용하면 클래스형 컴포넌트, render 등을 안해도 된다.
  • 모든 것은 하나의 function이 되는 것 함수형 프로그래밍이 가능해진다.

Basic Hooks

  • useState
  • useEffect
  • useContext

Additional Hooks

  • useReducer
  • useCallback
  • useMemo
  • useRef
  • useImperativeHandle
  • useLayoutEffect
  • useDebugValue

custom hook

  1. 커스텀 훅 사용 시 use를 앞에 붙어야 한다.
  2. 커스텀 훅 또한 useState와 같은 내장 훅을 사용한다.
  3. 커스텀 훅은 코드의 중복을 줄이고 재사용성을 높이며, 효율적인 관리를 위해 필요하다.
  4. 커스텀 훅은 기본 컴포넌트를 만들 때와 유사하고, JSX가 아닌 배열 혹은 오브젝트를 return 한다.
    즉, return [value]; 혹은 return {value};를 한다. 배열의 수와 오브젝트의 수는 개발자의 필요에 따라 추가 가능하다.
  5. 커스텀 훅을 사용하는 방법은 useState와 거의 유사하다.
    초기값을 파라미터로 넘겨주는 게 일반적이고 커스텀 훅이 배열을 return 했느냐 혹은 오브젝트를 return 했느냐에 따라 사용할 컴포넌트에 선언해주면 된다.
    value만 배열로 return : const [value] = useFetch('/api/something');
    value만 Object로 return : const {value} = useFetch('/api/something');
  6. 리액트의 컴포넌트는 하나 이상의 상태의 값이 변경되거나 Props의 값이 변경되면 리렌더링 된다.

참고자료

다루어 볼 Hooks

  1. useState
  2. useInput - custom hook
  3. useTabs - custom hook
  4. useEffect 작성한 링크
  5. useFetch - custom hook

🌈 useState 클래스형 컴포넌트와 함수형 컴포넌트 state 활용 차이점

클래스 컴포넌트에서의 state 선언

app.js

class App extends Component {
	state = {
    	count : 0
    };
	modify = n => {
    	this.setState({
        	count : n
        });
    };
	render(){
    	const {count} = this.state;
      	return(
        	<>
          		<div>{count}</div>
            	<button onClick={()=> this.modify(count +1)}>Increment</button>
          	</>
        )
    }
}

위에 코드를 보다시피 Class component가 필요하고 state도 필요하고 그걸 정의해야 하고 패스 해야하는 등등 많은 것들을 하게 되는 단점을 가지고 있다.

함수형 컴포넌트에서의 React Hook(useState) 사용하여 state 선언

app.js

const App = ()=>{
	const [count, setCount] = useState(0);
  	return(
    	<>
        	<button onClick = {()=>setCount(count + 1)}>Increment</button>
        </>
    )
}

React Hook을 사용하면 더 이상 class를 사용하지 않고 모든것이 함수형 프로그래밍을 할 수 있다.

React Hook의 좋은 점은 함수형 프로그래밍을 지원하는 것이다.

🌈 useState 카운터 구현

함수형컴포넌트 카운터

app.js

import React, { useState } from "react";

const App = () => {
  const [item, setItem] = useState(1);
  const incrementItem = () => setItem(item + 1);
  const decrementItem = () => setItem(item - 1);
  return (
    <div className="App">
      <h1>Hello {item}</h1>
      <h2>Start editing to see some magic happen!</h2>
      <button onClick={incrementItem}>increment</button>
      <button onClick={decrementItem}>decrement</button>
    </div>
  );
};

export default App;
  • hooks가 생기지전에 우리는 state를 함수형 component에 사용할 수 없었다.
  • state를 사용하고 싶으면 classComponent를 사용해야 되었다.
  • Class component에서 state를 사용하려면 this와 같은 문장 규칙과 Render를 고려해야한다.
  • 하지만 React hooks는 고려하지 않아도 된다.

클래스형 컴포넌트 카운터

app.js

Class AppUgly extends React.Component{
	state = {
		item : 1
	}
	render(){
		const {item} = this.state;
		return (<div className="App">
     			<h1>Hello {item}</h1>
      			<h2>Start editing to see some magic happen!</h2>
  			<button onClick={this.incrementItem}>increment</button>
    			<button onClick={this.decrementItem}>decrement</button>
    		     </div>);
	}
	incremxetitem = ()=>{
		this.setState(state => {
			return {
				item : state.item + 1
			};
		});
	};
	decrementItem = ()=>{
		this.setState(state => {
			return {
				item : state.item + 1
			};
		})
	}
};

📌 useInput custom hook

useInput hooks는 초기 value값을 셋팅해주고 내부에 onChange 메서드를 사용하여 입력창에 텍스트가 업데이트 될 때 마다 콘솔에 입력해주는 함수를 생성하였다.

import React, { useState } from "react";

const useInput = (initialValue) => {
  const [value, setValue] = useState(initialValue);
  const onChange = (event) => {
    console.log(event.target);
  };
  return {
    value,
    onChange
  };
};

const App = () => {
  const name = useInput("Mr.");

  return (
    <div className="App">
      <h1>Hello</h1>
      <input placeholder="Name" {...name} />
      //주요 구문 전개연산자 & 디스트럭쳐의 조합
    </div>
  );
};

export default App;

위 코드는 App component가 아니라 완전히 다른 function에서 이벤트를 처리할 수 있다.

결론
우리의 이벤트를 분리된 파일, 다른 entitiy에 연결해서 처리할 수 있다.

📌 useInput custom hook 활용

유효성 검사

코드를 살펴 보기 전 확인해야 될 문법)

  1. destructuring 문법
const [value, setValue] = useState(initialValue);
const onChange = (event)=> {
	const {
    	target : { value }
    } = event;
  	// = `const value = event.target.value;` 위에 있는 코드와 같은 코드이다.
  	...
}
  1. spread Operator 문법
    name변수에 할당된 값은 useInput 값의 리턴값인 value,onChange이다. input의 속성으로 valueonChange가 존재하므로 전개연산자를 사용하여 쉽게 만들어 줄 수 있다.

활용

const useInput = (initialValue, validator)=>{
	...
  	return {
    	value,
        onChange
    }
}
const App = ()=> {
	const name = useInput("Mr.", maxLen);
  	return(
		<input placeholder="Name" {...name} />		
    )
}

app.js

import React, { useState } from "react";

const useInput = (initialValue, validator) => {
  const [value, setValue] = useState(initialValue);
  //유효성 검사를 하기 위한 코드 구현
  const onChange = (event) => {
    const {
      target: { value }
    } = event;
    let willUpdate = true;
    if (typeof validator === "function") {
      willUpdate = validator(value);
    }
    if (willUpdate) {
      setValue(value);
    }
    console.log(value);
  };
  return {
    value,
    onChange
  };
};

const App = () => {
  //inpu에 10이하 문자열만 입력되게 하기
  const maxLen = (value) => value.length <= 10;
  const name = useInput("Mr.", maxLen);

  return (
    <div className="App">
      <h1>Hello</h1> 
      <input placeholder="Name" {...name} />
    </div>
  );
};

export default App;

📌 useTabs custom hook 활용2

import { useState } from "react";

const content = [
    {
    tab: "Section 1",
    content: "I'm the content of the Section 1"
    },
    {
    tab: "Section 2",
    content: "I'm the content of the Section 2"
    }
  ];
  
  const useTabs = (initialTab, allTabs) => {
    const [currentIndex, setCurrentIndex] = useState(initialTab);
    if (!allTabs || !Array.isArray(allTabs)) {
      return ;
    }
    return {
      currentItem: allTabs[currentIndex],
      changeItem: setCurrentIndex
    };
  };
  
  const App = () => {
    const {currentItem, changeItem} = useTabs(1, content);
    console.log(currentItem,changeItem)
    return (
      <div className ="App">
        {
        content.map((section, index)=>{

          return(
            <button onClick={()=> changeItem(index)}>{section.tab}</button>
          )
        })
        }
        <div>{currentItem.content}</div>
      </div>
     );
  }

  export default App;

📌useFetch custom hook

Promise Fetch hook

useFetch.js

import { useEffect, useState } from "react";

export default function useFetch(url) {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch(url)
      .then(res => {
        return res.json();
      })
      .then(data => {
        setData(data);
      });
  }, [url]);

  return data;
}

사용
Day.jsx

import useFetch from "../hooks/useFetch";
import { useParams } from "react-router-dom";

export default function Day(){
	const {day} = useParams();    
    const words = useFetch(`http://localhost:3001/words?day=${day}`);

    return(
        <>
			...
        </>
    )
}
profile
오늘보단 내일이 강한 개발자입니다!🧑🏻‍💻
post-custom-banner

0개의 댓글