본문 바로가기

Study/React

custom Hooks

what is custom Hooks? 

  1. custom hooks도 결국 일반적인 함수의 하나이다.
  2. 단, 다른 함수들과 달리 블럭 안에 stateful logic을 포함할 수 있다. => hooks와 state를 사용할 수 있다. 
  3. 이 때 어플리케이션에서 중복으로 사용되고 있는 로직을 커스텀 훅으로 만들면, 여러 곳에서 재사용할 수 있다.
    • 로직은 공유하고, state는 따로 갖는다.  
  4. src/hooks 폴더를 만들어서 관리한다. 
  5. remind | rules of hooks
    • 컴포넌트 함수/ 커스텀 훅이 아닌 함수 안에서는 리액트 훅을 사용할 수 없다. 
    • (컴포넌트/커스텀)함수의 top level(direct level)에서 리액트 훅을 호출해야 한다. 

how to make customHooks?

// use-counter.js
const useCounter = (props) => {
  const [counter, setCounter] = useState(0);

  useEffect(()=>{
      const timer = setInterval(() =>{
          setCounter(prev => prev+1);
      }, 10000)
      // 디펜던시가 있을 때에는 clear fn이 없으면 interval 함수가 쌓이기 때문 
      return () => clearInterval(timer); 
  }, [])
  
  return counter; 
}

// App.js
import useCounter from '../hooks/use-counter'
function App() {
  const counter = useCounter(); // returning state 
  
  return (
    <>
      <h1>forward : {counter}</h1>
      <h1>backward : {counter}</h1>
    </>
  )
}

 

  1. 커스텀 훅을 저장하고 있는 변수 명은 반드시 use로 시작해야 한다.
    • 이것은 리액트에게 해당 함수가 일반 함수가 아니라, 커스텀 훅이라는 것을 명시할 뿐만 아니라, 
    • 해당 함수에서 rules of hooks를 따르겠다고 약속하는 것이다. 
  2. 다른 컴포넌트에서 커스텀 훅을 호출하면, 커스텀 훅에서 사용하고 있는 state, effect 등이 컴포넌트에 묶인다(tied).
    • 여러 컴포넌트에서 같은 커스텀 훅을 호출하더라도, 모든 컴포넌트가 각자의 state를 갖는다. => re-useable 
  3. return | useState()가 배열을 반환하는 것처럼, 커스텀 훅이 어떤 값을 반환할지 정할 수 있다.
  4. parameter |  커스텀 훅도 함수이기 때문에 당연히 인자를 받을 수 있다. 

 

const useCounter = (counterFn) => { // params
  const [counter, setCounter] = useState(0);

  useEffect(()=>{
      const timer = setInterval(() =>{
          setCounter(counterFn); // (prev)=> prev + 1 또는 -1 
      }, 10000)
      return () => clearInterval(timer);
  }, [counterFn]) // effect가 외부 데이터를 사용하고 있으므로 dependencies 전달
  
  return counter; 
}

useHttp hook

post request option 

{        
  method: 'POST',
  body: JSON.stringify({ text: userInput }), // 사용자가 입력한 값을 json으로 변환하여 백엔드에 전달
  headers: {
    'Content-Type': 'application/json',
  },
}

how to make useHttp?

http request에서 공통적으로 사용될 수 있는 로직에는 다음과 같은 것들이 있다. 

 

  1. loading state
  2. fetch 
  3. error state & handling (try - catch)

 

const useRequest = (props) => {
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  const sendRequest = useCallback(async (config, transformData) => {
    try {
      setIsLoading(true);
      const res = await fetch(config.url, {
        method: config.method ? config.method : 'GET',
        headers: config.headers ? config.headers : {},
        body: config.body ? JSON.stringify(config.body) : null,
      });

      if (!res.ok) throw new Error('Request Error!');

      const data = await res.json();
      transformData(data);
    } catch (error) {
      setError(error.messages || 'something wrong');
    }
    setIsLoading(false);
  }, []);

  return { isLoading, error, sendRequest };
};

export default useRequest;

 

  1. sendRequest를 반환해서 컴포넌트 안에서도 이 함수를 사용할 수 있게 만든다. 
  2. key로 접근하기 위해서 배열 대신 객체를 반환한다. 
  3. useCallback( (config, transformData) => sendReq, []) 
    • sendReq가 외부 데이터를 사용하지 않기 때문에 === dependency가 없다. 

 

const { isLoading, error, sendRequest } = useRequest();

const enterTaskHandler = (taskText) => {
    const config = {
      url: '백엔드 url',
      method: 'POST',
      body: { text: taskText },
      headers: { 'Content-Type': 'application/json' },
    };
    const transformData = (data) => {
      const generatedId = data.name;
      const createdTask = { id: generatedId, text: taskText };
      props.onAddTask(createdTask);
    };

    sendRequest(config, transformData);
  };

 

+) fn.bind(fn의 this가 가리킬 값, fn이 실행될 때 인자로 사용될 값) | bind는 나중에 실행 될 fn을 준비(pre-configure)하는 역할을 한다.

  • this가 가리킬 값을 null로 지정하면, fn이 원래 가리킬 this를 그대로 사용한다.  
  • ()=>{ greet('max') }와 greet.bind(null, 'Max')는 같다. 이 때 bind가 가리키는 this는 greet이다. 

 

someButton.addEventListener('click', greet.bind(null, 'Max'));

 

'Study > React' 카테고리의 다른 글

Deployment | firebase hosting  (0) 2022.07.04
Validation  (0) 2022.06.27
HTTP Request  (0) 2022.06.23
Optimization | how does react work?  (0) 2022.06.22
etc | Image, Icon, Input  (0) 2022.06.21