[Hook] - Custom Hook

Donggu(oo)·2023년 1월 25일
0

React

목록 보기
24/30
post-thumbnail

1. Custom Hook의 예시


1) useInput

  • 여러 input 상태 변경을 할 때 쓸 수 있는 useInput Hook이다.
import { useState, useCallback } from 'react';

function useInput(initialForm) {
    const [form, setForm] = useState(initialForm);
    // change
    const onChange = useCallback(e => {
        const { name, value } = e.target;
        setForm(form => ({ ...form, [name]: value }));
    }, []);
    const reset = useCallback(() => setForm(initialForm), [initialForm]);
    return [form, onChange, reset];
}

export default useInput;
  • 기존의 App.js에서 input 부분을 커스텀 훅으로 따로 분리한 후, input 요소도 별도의 컴포넌트로 분리했다.
// 원본 App.js
import { useState } from "react";
import "./styles.css";

export default function App() {
  const [firstNameValue, setFirstNameValue] = useState("");
  const [lastNameValue, setLastNameValue] = useState("");
  const [nameArr, setNameArr] = useState([]);

  const handleSubmit = (e) => {
    e.preventDefault();
    setNameArr([...nameArr, `${firstNameValue} ${lastNameValue}`]);
  };

  return (
    <div className="App">
      <h1>Name List</h1>
      <div className="name-form">
        <form onSubmit={handleSubmit}>
          <div className="name-input">
            <label></label>
            <input
              value={firstNameValue}
              onChange={(e) => setFirstNameValue(e.target.value)}
              type="text"
            />
          </div>
          <div className="name-input">
            <label>이름</label>
            <input
              value={lastNameValue}
              onChange={(e) => setLastNameValue(e.target.value)}
              type="text"
            />
          </div>
          <button>제출</button>
        </form>
      </div>
      <div className="name-list-wrap">
        <div className="name-list">
          {nameArr.map((el, idx) => {
            return <p key={idx}>{el}</p>;
          })}
        </div>
      </div>
    </div>
  );
}
// App.js

import useInput from "./util/useInput";
import Input from "./component/Input";
import "./styles.css";
import { useState } from "react";

export default function App() {
  const [firstInputValue, firstHandleChange, firstReset] = useInput('');
  const [lastInputValue, lastHandleChange, secondReset] = useInput('');
  const [nameArr, setNameArr] = useState([]);

  const handleSubmit = (e) => {
    e.preventDefault();
    setNameArr([...nameArr, `${firstInputValue} ${lastInputValue}`]);
    firstReset();
    secondReset();
  }

  return (
    <div className="App">
      <h1>Name List</h1>
      <div className="name-form">
        <form onSubmit={handleSubmit}>
          <Input labelText={'성'} value={firstInputValue} handleChange={firstHandleChange} />
          <Input labelText={'이름'} value={lastInputValue} handleChange={lastHandleChange} />
          <button>제출</button>
        </form>
      </div>
      <div className="name-list-wrap">
        <div className="name-list">
          {nameArr.map((el, idx) => {
            return <p key={idx}>{el}</p>;
          })}
        </div>
      </div>
    </div>
  );
}
// useInput.js
import { useState } from "react";

function useInput(initialValue, initialArr) {
  const [inputValue, setInputValue] = useState(initialValue);

  const handleChange = (e) => {
    setInputValue(e.target.value);
  }
  // submit 버튼 클릭시 input 초기화 함수
  const reset = () => {
    setInputValue(initialValue);
  }

  return [inputValue, handleChange, reset];
}

export default useInput;
// Input.js
function Input({ labelText, value, handleChange }) {
  
  return (
    <div className="name-input">
      <label>{labelText}</label>
      <input
        value={value}
        onChange={handleChange}
        type="text"
      />
    </div>
  )
}

export default Input;

2) useFetch

  • 여러 url을 fetch할 때 쓸 수 있는 useFetch Hook이다.
const useFetch = (initialUrl: string) => {
    const [url, setUrl] = useState(initialUrl);
    const [value, setValue] = useState('');

    const fetchData = () => axios.get(url).then(({ data }) => setValue(data));

    useEffect(() => {
        fetchData();
    }, [url]);

    return [value];
};

export default useFetch;
  • 기존의 App.js에서 fetch 부분을 커스텀 훅으로 따로 분리했다.
// App.js
import "./styles.css";
import { useEffect, useState } from "react";

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

  useEffect(() => {
    fetch("data.json", {
      headers: {
        "Content-Type": "application/json",
        Accept: "application/json"
      }
    })
      .then((response) => {
        return response.json();
      })
      .then((myJson) => {
        setData(myJson);
      })
      .catch((error) => {
        console.log(error);
      });
  }, []);

  return (
    <div className="App">
      <h1>To do List</h1>
      <div className="todo-list">
        {data &&
          data.todo.map((el) => {
            return <li key={el.id}>{el.todo}</li>;
          })}
      </div>
    </div>
  );
}
// App.js
import "./styles.css";
import useFetch from "./util/hooks";

export default function App() {
    const data = useFetch('data.json')

    return (
        <div className="App">
            <h1>To do List</h1>
            <div className="todo-list">
                {data &&
                    data.todo.map((el) => {
                        return <li key={el.id}>{el.todo}</li>;
                    })}
            </div>
        </div>
    );
}
// useFetch.js
import { useState, useEffect } from "react";

const useFetch = (fetchUrl) => {
    const [data, setData] = useState(null);

    useEffect(() => {
        fetch(fetchUrl, {
            headers: {
                "Content-Type": "application/json",
                Accept: "application/json"
            }
        })
            .then((response) => {
                return response.json();
            })
            .then((myJson) => {
                setData(myJson);
            })
            .catch((error) => {
                console.log(error);
            });
    }, [fetchUrl]);

    return data;
};

export default useFetch;

0개의 댓글