Building Custom Hooks

김민경·2023년 2월 10일
0

FE(WEB) - React

목록 보기
12/13

🎈 What is a Custom Hook?

🎈 Why use Custom Hook?

when there is a circumstance of code duplication of two components doing the similar task

🎈 Building a Custom Hook

(Ex1) ForwardCounter and BackwardCounter

  • the component should start with the name use~

src/hooks/use-counter.js

import { useState, useEffect } from 'react';

// can get a parameter
// can also set a default value of a parameter
const useCounter = (forwards) => {
	const [counter, setCounter] = useState(0);
    
    useEffect(()=> {
    	const interval = setInterval(() => {
        if (forwards) {
        	setCounter((prevCounter) => prevCounter + 1);
        } else {
        	setCounter((prevCounter) => prevCounter - 1);
        }
        }, 1000);
        
        return () => clearInterval(interval);
    }, [forwards]);
    // since a parameter is a new dependency,
    // we should add it a dependenct in useEffect
    
    return counter;
};

export default useCounter;

using custom hooks

ForwardCounter.js

import useCounter from ~

const ForwardCounter = () => {
	const counter = useCounter(true);
    return <Card>{counter}</Card>
}

BackwardCounter.js

import useCounter from ~

const BackwardCounter = () => {
	const counter = useCounter(false);
    return <Card>{counter}</Card>
}

(Ex2) Requesting GET and POST request

code it flexibily considering the dependencies of useEffect and useCallback (since putting all the states/functions used in a function as dependencies can trigger an infinite loop)

hooks/use-https.js

const useHttp = (⭐ applyData) => {
	const [isLoading, setIsLoading] = useState(false);
  	const [error, setError] = useState(null);

  	const sendRequest = ✨ useCallback(async (✨⭐ requestConfig) => {
    	setIsLoading(true);
    	setError(null);
    	try {
     		const response = await fetch(⭐ requestConfig.url, {
        		method: ⭐ requestConfig.method ? requestConfig.method : 'GET',
        		headers: ⭐ requestConfig.headers ? requestConfig.headers : {},
        		body: requestCofnig.body ? JSON.stringify(⭐ requestConfig.body) : null,
      		});

      		if (!response.ok) {
        		throw new Error('Request failed!');
      		}

      		const data = await response.json();
      		⭐ applyData(data);
    	} catch (err) {
      		setError(err.message || 'Something went wrong!');
    	}
    	setIsLoading(false);
  	}, [applyData]);
    // requestConfig and applyData, which should be applied as dependencies
    // are reference types
    // -> ✨ use useCallback() in transformTasks!
    // for requestConfig, we can use useMemo
    // -> ✨ or use as a parameter for sendRequest

  	return {
    	isLoading,
    	error,
    	sendRequest,
  	};
}

export deault useHttp;

App.js - send GET request

// using custom hook
import useHttp from ~

function App() {
	const [tasks, setTasks] = useState([]);
    
    const transformTasks = ✨ useCallback(taskObj) => {
    	for (const taskKey in taskObj) {
        	loadedTasks.push({id: taskKey, text : taskObj[taskKey].text});
        }
        
        setTasks(loadedTasks);
    }, []);
    
    const { isLoading, error, sendRequest : fetchTasks } = useHttp(transformTasks);
    
    useEffect(() => {
    	fetchTasks({url : "the api url for GET request"});
    }, [fetchTasks]);
    // if putting fetchTasks as dependency, it will create an infinite loop
    // -> ✨ use useCallback() in sendRequest! 
}

sending a POST request can be coded in a similar way

profile
🏛️❄💻😻🏠

0개의 댓글