기억의 실마리
2022. 11. 3. 21:45

# useNetwork의 기능

 

import {useEffect, useState} from "react";

export const useNetwork = (onChange) => {
    const [status, setStatus] = useState(navigator.onLine);
    const handleChange = () => {
        if (typeof onChange === "function") {
            onChange(navigator.onLine);
        }
        setStatus(navigator.onLine);
    };
    useEffect(() => {
        window.addEventListener("online", handleChange);
        window.addEventListener("offline", handleChange);

        return () => {
            window.removeEventListener("online", handleChange);
            window.removeEventListener("offline", handleChange);
        };
    }, []);
    return status;
};

useNetwork는 네트워크의 상태가 온라인인지 오프라인인지 확인할 수 있는 hook이다.


반환값은 boolean형이다. ( true = online && false = offline )

 

 

# 설명

 

const [status, setStatus] = useState(navigator.onLine);

useState의 디폴트값은 navigator.onLine 이다.

 

navigator는 브라우저에 대한 버전, 정보, 종류 등 여러속성을 가져올 수 있다.

 

이 후에 onLine으로 접근을 했기 때문에 onLine이면 ture, offLine이면 false를 반환한다.

 

 

const handleChange = () => {
    if (typeof onChange === "function") {    //onChange는 useNetwork의 Argument이다.
        onChange(navigator.onLine);
    }
    setStatus(navigator.onLine);
};

handleChange 함수를 만들어주고, 내용은 useNetwork의 Argument인 onChange가 함수일때

 

함수를 실행할 수 있도록 유효성검사를 거친 후에

 

setStatus함수를 통해서 status를 re-render 시켜주는 기능이다.

 

 

useEffect(() => {
    window.addEventListener("online", handleChange);
    window.addEventListener("offline", handleChange);

    return () => {
        window.removeEventListener("online", handleChange);
        window.removeEventListener("offline", handleChange);
    };
}, []);

return status; // useNetwork의 return값.

useEffect를 사용하여 window에 ( on / offLine 이벤트 )를 걸어주고 실행시킬 함수는 handleChange로 넣어준다.

 

컴포넌트가 실행되지 않을땐 이벤트를 삭제해주는 함수를 넣는다.

 

이 후 re-render된 status를 반환한다(true or false).

 

 

# 사용예시

 

 const handleNetworkChange = online => {
   console.log(online ? "We just went online" : "We are offline");
 };
 const onLine = useNetwork(handleNetworkChange);

 <h1>{onLine ? "Online" : "Offline"}</h1>

handleNetworkChange라는 새로운 변수를 만들어주고 해당속성에 직접 접근하기 위해서

 

매게변수 online 을 넣어준 후 콘솔로그를 만들어서 true일때와 false일때 반응하는 기능을 각각 넣어준다.

 

이 후에 onLine 이라는 새로운 변수를 만들고 useNetwork를 사용하고

 

전달인자에 handleNetworkChange함수를 넣어준다.

 

이렇게 되면 useNetwork는 status를 반환하고,

 

status는 boolean형으로 값을 반환하기 때문에

 

콘솔로그가 online일땐( true ) "We just went online" ,

 

offline일땐( false ) "We are offline" 로 찍히게 된다.

'Frontend > React-Hooks' 카테고리의 다른 글

[ React Hook ] 7. useFadeIn  (0) 2022.11.05
[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 4. usePreventLeave  (0) 2022.11.02
[ React Hook ] 3. useTabs  (0) 2022.10.31
[ React Hook ] 2. useTitle  (0) 2022.10.30
2022. 11. 2. 20:07

# usePreventLeave의 기능

 

export const usePreventLeave = () => {
    const listener = (event) => {
        event.preventDefault();
        event.returnValue = "";
    };
    const enablePrevent = () =>
        window.addEventListener("beforeunload", listener);
    const disablePrevent = () =>
        window.removeEventListener("beforeunload", listener);
    return { enablePrevent, disablePrevent };
};

usePreventLeave는 웹사이트를 나가려고 할 때 알람문구를 띄워 한번 더 묻는 기능이 필요할때 사용한다.

 

useState나 useEffect를 사용하지 않은 순수함수로 만든 hook이다.

 

 

# 설명

 

const listener = (event) => {
        event.preventDefault();
        event.returnValue = "";
    };

우선 리스너 함수를 만든 후 기본옵션을 막아준다.

 

전달인자로부터 returnValue = ""; 를 해준다. 만약 이 작업을  하지않는다면,

 

이 후에 사용될 이벤트인 " beforeunload " 가 실행되지 않는다. 

 

 

const enablePrevent = () =>
    window.addEventListener("beforeunload", listener); //이벤트 추가
const disablePrevent = () =>
    window.removeEventListener("beforeunload", listener); //이벤트 삭제

이 후 이벤트 추가 함수와(enablePrevent), 삭제 함수(disablePrevent)를 만들어준다.

 

beforeunload 가 되면 listener함수를 실행하도록 만들면 된다.

# 사용예시

 

	const usePreventLeave = () => {
    
    	... // (내용 생략)
        
        return { enablePrevent, disablePrevent };
    };
    
    const {enablePrevent, disablePrevent} = usePreventLeave();
    
	<button onClick={enablePrevent}/>
    <button onClick={disablePrevent}/>

usePreventLeave는 enablePrevent와 disablePrevent를 반환하고

 

사용할때는 간단하게 사용하기 위해서 구조분해할당을 사용한다.

 

<button onClick={enablePrevent}/> 를 클릭하면 이벤트가 실행돼서 alert처럼 알람문구가 뜨게되고

 

취소를 누르면 웹사이트를 유지, 승인을 누르면 웹사이트를 나간다.

 

반대로 <button onClick={enablePrevent}/> 를 누른 후에 <button onClick={disablePrevent}/> 를 누르면

 

추가되었던 이벤트가 취소되기 때문에 웹사이트를 나가면 알람문구가 뜨지않고 바로 나가진다.

'Frontend > React-Hooks' 카테고리의 다른 글

[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
[ React Hook ] 3. useTabs  (0) 2022.10.31
[ React Hook ] 2. useTitle  (0) 2022.10.30
[ React Hook ] 1. useInput  (0) 2022.10.30
2022. 10. 31. 23:10

 

# useTabs의 기능

 

import {useState} from "react";

export const useTabs = (initialTab, allTabs) => {
    if (!allTabs || !Array.isArray(allTabs)) {
        return;
    }

    const [currentIndex, setCurrentIndex] = useState(initialTab);
    return {
        currentItem: allTabs[currentIndex],
        changeItem: setCurrentIndex
    };
}

 

useTabs는 배열이나 객체의 값을 useState의 별도사용 없이 re-render시켜주는 hook이다.

 

사용법 :  useTabs를 새로운 변수에 할당하고 컴포넌트에 넣어서 사용한다.

 

 

# 예시

 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 {currentItem, changeItem} = useTabs(1, content);
 <div className="App">
      {content.map((section, index) => (
        <button onClick={ ()=> changeItem(index) }>{section.tab}</button>
      ))}
      <div>{currentItem.content}</div>
 </div>

위와 같이 예시로 content 라는 배열내에 객체 리터럴을 반환하는 변수가 있다.

 

그리고 구조분해할당을 사용하여 useTabs에서 반환값인 currentItem 와 changeItem를 가져와서

 

컴포넌트 내부에 넣어서 사용할 수 있다.

 

 

# 설명

import {useState} from "react";

export const useTabs = (initialTab, allTabs) => {
    if (!allTabs || !Array.isArray(allTabs)) {
        return;
    }

    const [currentIndex, setCurrentIndex] = useState(initialTab);
    return {
        currentItem: allTabs[currentIndex],
        changeItem: setCurrentIndex
    };
}

      /*     아래부터는 적용예시이다.     */
      
 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 {currentItem, changeItem} = useTabs(1, content);
 <div className="App">
      {content.map((section, index) => (
        <button onClick={ ()=> changeItem(index) }>{section.tab}</button>
      ))}
      <div>{currentItem.content}</div>
 </div>

useTabs의 구조와 예시는 이러하고

 

 

const useTabs = (initialTab, allTabs)

첫번째 전달인자(argument)는 초기에 default 로 render될 리터럴을 넣는다.

 

지금 예시는 배열형태이기 때문에 숫자를 넣어주면 된다. (예시를 기준으로 [ 0, 1 ] 이있다.)

 

그리고 두번째 전달인자는 정보를 가져올 배열의 변수를 넣어준다. ( content )

 

 

    if (!allTabs || !Array.isArray(allTabs)) {
        return;
    }

if문으로 allTabs가 false이거나 Array가 아닌경우에는 실행되지 않도록 브레이크를 걸어준다.

 

 

const [currentIndex, setCurrentIndex] = useState(initialTab);

이 후에 useState를 이용하여 useTabs에서 받아온 첫번째 전달인자인 initialTab을 default로 두고

 

re-render될 수 있는 상태가 되도록 만든다.

 

 

    return {
        currentItem: allTabs[currentIndex],
        changeItem: setCurrentIndex
    };

그리고 useTabs의 반환값은 위와 같다.

 

 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"
    }
 ]

정보를 가져올 배열 content이다.

 

 const {currentItem, changeItem} = useTabs(1, content);
 <div className="App">
      {content.map((section, index) => (
        <button onClick={ ()=> changeItem(index) }>{section.tab}</button>
      ))}
      <div>{currentItem.content}</div>
 </div>

useTabs에서 반환값인 currentItem과  changeItem을 꺼낸다 ( 구조분해할당 )

 

currentItem = 배열전체 [  렌더링함수로인해서 바뀐 렌더링 벨류  ]
changeItem = 렌더링함수()

 

이렇게 이해를 하고 있어야  더 쉽다.

 

# 컴포넌트 적용예시

      {content.map((section, index) => (
        <button onClick={ ()=> changeItem(index) }>{section.tab}</button>
      ))}

# .map

배열 content에서 .map 을 사용해서 모든 배열에 각각 함수를 만들어서 반환하게 만들어준다.(forEach와 같은구조)

 

section이라는 첫번째 매게변수를 만들고( content로 접근할 수 있는 매게변수 )

 

두번째 매게변수는 index로 .map에서 기본으로 제공하는 기능으로

 

배열의 순서대로 { index : 순서 } 의 속성이 들어간다. content는 0, 1이 있으니

 

0번째 배열에는 { index: 0 }, 1번째 배열에는 { index: 1 } 이라는 속성이 만들어지고

 

{ index: 0 }을가진 버튼 하나와 { index: 1 }을 가진 버튼, 총 2개의 버튼을 만든다.

 

# - button onClick -

버튼에 온클릭 이벤트를 만들어주고 내용은 changeItem(index) 이다.

 

 changeItem = 렌더링함수() 이기때문에  setCurrentIndex( index ) 가 된다.

 

그렇게 되면 currentIndex는 전달받은 index로 re-render되고

 

currentItem : allTabs[ currentIndex ] 이므로 

 

currentItem은 클릭했을때 해당 index에 일치하는 배열순서의 객체리터럴(값)을 가져온다.

( 배열전체 [  렌더링함수로인해서 바뀐 렌더링 벨류  ] )

 

 

# 컴포넌트 내용

 	content.map((section, index) => { ... } )

내용은  {section.tab}  이다.

 

section은 단순하게 함수가 적용된 해당요소에 접근하기 위한 매게변수이기때문에

 

{section.tab} = {conent.tab}  과 같다. 즉 버튼의 내용은 각 index에 맞게 tab(key)의 value로 나타난다.

(Section 1)   (Section 2)      < == 이런 버튼이 나온다.

 

<div>{currentItem.content}</div>

위에서 말했던

 

------------------------------------------------------------------------------------------------

 

currentItem : allTabs[ currentIndex ] 이므로 

 

currentItem은 클릭했을때 해당 index에 일치하는 배열순서의 객체리터럴(값)을 가져온다.

( 배열전체 [  렌더링함수로인해서 바뀐 렌더링 벨류  ] )

 

 -----------------------------------------------------------------------------------------------

이 부분이고

 

{클릭한 녀석의 객체리터럴}.content 이므로 

 

위에 버튼 (Section 1) 을 클릭하면

I'm the content of the Section 1

 

위에 버튼 (Section 2) 을 클릭하면

I'm the content of the Section 2

 

이렇게 내용을 보여준다.

'Frontend > React-Hooks' 카테고리의 다른 글

[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
[ React Hook ] 4. usePreventLeave  (0) 2022.11.02
[ React Hook ] 2. useTitle  (0) 2022.10.30
[ React Hook ] 1. useInput  (0) 2022.10.30
2022. 10. 30. 22:41

 

# useTitle의 기능

 

import {useEffect, useState} from "react";

export const useTitle = initialTitle => {
    const [title, setTitle] = useState(initialTitle);
    const updateTitle = ()=> {
        const htmlTitle = document.querySelector("title");
        htmlTitle.innerText = title;
    };
    useEffect(updateTitle, [title]);
    return setTitle;
}

useTitle은 HTML에서 Head에 있는 title을 바꿔주는 기능이다.

 

상태에 따른 타이틀 변화를 주고싶을때 사용하는 Hook이다.

 

사용법 :  useTitle을 새로운 변수에 할당하고 컴포넌트에 넣어서 사용한다.

 

	const titleUpdater = useTitle("loading...");
	//타이틀의 디폴트를 "loading..." 으로 바꿔 줄 수 있다. 
    
 	setTimeout(()=> titleUpdater("Home"),5000);
 	//타임아웃을 추가하면 적용한 시간 후에(지금은 5초) 타이틀이 loading... => Home 으로 바뀐다.

useTitle은 아주 간단한 훅이기 때문에 추가 설명보다는 기본적인 useState와 useEffect의 기능적인 이해가 더 중요하다.

'Frontend > React-Hooks' 카테고리의 다른 글

[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
[ React Hook ] 4. usePreventLeave  (0) 2022.11.02
[ React Hook ] 3. useTabs  (0) 2022.10.31
[ React Hook ] 1. useInput  (0) 2022.10.30
2022. 10. 30. 17:56

 

# useInput의 기능

 

import {useState} from "react";

export 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);
        }
    };
    return {value, onChange};
}

react내에서 input을 사용하고자 할때 사용하는 함수(hook)이다.

 

인풋에 입력하는 값을 useState의 별도사용 없이 re-render시켜주는 hook이다.

 

사용법 :  useInput을 새로운 변수에 할당하고 컴포넌트에 넣어서 사용한다.

 

 

const inputArea = useInput("MR.", cantWord);
const cantWord = (value) => !value.includes("!");

<input placeholder="inputArea" {...inputArea} />

useInput의 첫번째 전달인자( Argument )는 해당 인풋의 초기값이 되고

 

두번째 전달인자는 Input의 유효성검사, 새로운 규칙의 함수를 넣을 수 있다.

 

현재 새로운 규칙  cantWord의 내용은 인풋안에 느낌표가 들어가면 펄스를 반환하여 re-render를 하지 않게 된다.

 

여기서 { ...inputArea } 는 inputArea의 모든 것을 언팩한다.

 

inputArea = useInput

 

즉 useInput의 return값인 { value, onChange }는 input의 속성이 된다.

 

 

# 설명

 

const inputArea = useInput("MR.", cantWord);
const cantWord = (value) => !value.includes("!");

<input placeholder="inputArea" {...inputArea} />

 

{ ...inputArea } 를 통해서 useInput의 반환값인 value와 onChange를 가져왔다.

 

onChange는 변화를 감지하는 이벤트이고 Javascript Vanilla 에서는 addEventListener("change", function) 와 같다.

 

리액트에서는 컴포넌트 속성내부에 넣는 것만으로도 이벤트가 실행된다.

 

onChange에 따로 전달인자를 정해주지 않았기 때문에

 

전달인자(Argument) = "해당함수가 실행되는 요소의 속성" 이 된다.

 

 

    const onChange = event => {
    
        const { target: {value} } = event;
        
        let willUpdate = true;
        
        if (typeof validator === "function") {
            willUpdate = validator(value);
        }
        if (willUpdate) {
            setValue(value);
        }
    };

그러므로 event는 input속성에 접근할 수 있는 인자가 되었고

 

구조분해 문법을 사용해서 event의 target: { value } 를 가져오고

 

이후에 쓰이는 value = "input내부의 적힌 값" 이 된다.

 

이후에 if문을 통해서 함수의 유효성을 검사 한 후, 함수가 맞으면

 

validator가 실행되고  willUpdate = validator(value) 가 됨으로 이 함수가 제대로 작동하게되면 true이고

 

useState의 리렌더 함수인 setValue가 실행되면 쓰는대로 글자가 적힌다.

'Frontend > React-Hooks' 카테고리의 다른 글

[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
[ React Hook ] 4. usePreventLeave  (0) 2022.11.02
[ React Hook ] 3. useTabs  (0) 2022.10.31
[ React Hook ] 2. useTitle  (0) 2022.10.30