기억의 실마리
2022. 11. 14. 23:20

1. Real Time 기능 게시글과 이어지는 내용이다.

글을 입력하고 업로드하면 마운트되는 컴포넌트의 이름은 Zweet이며

 

Zweet.js내부에 단독으로 존재한다. ( 아래 내용들 모두 Zweet.js의 내용 )

 

# 메소드 영역

import React, {useState} from "react";
import {dbService} from "../Fbase";  //Fbase.js에서 가져온 변수이고 getFirestore메소드이다.
import {deleteDoc, doc, updateDoc } from "firebase/firestore";


export const Zweet = ({ zweetObj, isOwner })=> {   
//zweetObj = 최신화된 유저오브젝트 , isOwner = 글쓴이가 맞는지 여부

    const [editing, setEditing] = useState(false);            //에디트 활성화 여부
    const [newZweet, setNewZweet] = useState(zweetObj.text);  //에디트input의 text
    
    const zweetTextRef = doc(dbService, "zweets", `${zweetObj.id}`);
    //중복코드를 변수로 선언
    
    const onDeleteClick = async () => {
        const ok = window.confirm("Are you sure you want to delete this zweet?");
        if(ok){
            await deleteDoc(zweetTextRef);
        }
    };
    //confirm메소드를 사용하여 boolean값을 받고 true면 deleteDoc메소드를 실행한다
    
    const toggleEditing = () => setEditing((prev)=> !prev);   //에디트를 활성화/비활성화 시킨다
    const onChange = ({target:{value}})=> setNewZweet(value); //벨류가 바뀌면 re-render시킨다
    
    const onSubmit = async (e) => {
        e.preventDefault();
        await updateDoc(zweetTextRef,{
            text: newZweet,
        });
        setEditing(false);
    };
    //text를 newZweet의 value로 바꿔서 업데이트하고 다시 에디트를 비활성화 시켜준다.

 

# 컴포넌트 마운트 영역

    return (
        <div>
            {
                editing ? (
                    <>
                        <form onSubmit={onSubmit}>
                            <input type="text"
                                   placeholder="Edit your zweet"
                                   value={newZweet}
                                   required
                                   onChange={onChange}
                            />
                            <input
                                type="submit"
                                value="Update Zweet"
                            />
                        </form>
                        <button onClick={toggleEditing}>Cancel</button>
                    </>
                ) : (
                    <>
                        <div>
                            <h4>{zweetObj.text}</h4>
                            {isOwner && (
                                <>
                                    <button onClick={onDeleteClick}>Delete Zweet</button>
                                    <button onClick={toggleEditing}>Edit Zweet</button>
                                </>
                            )}
                        </div>
                    </>
                )
            }
        </div>
    );

에디트컴포넌트의 Default 값은 false이기 때문에 unmount이다. 에디트 버튼을 클릭할 경우 toggleEditing함수가 실행되어서 editing = true가 되고 에디트컴포넌트가 mount 된다. 이 후 input에 글을 수정하여 submit시키면(Enter or Edit Zweet 버튼) onSubmit함수에 의해 updateDoc메소드가 실행되어 업데이트되고 onSubmit의 로직처리중 마지막, setEditing(false)로 인해 다시 에디트컴포넌트는 unmount되고 홈컴포넌트가 mount된다.

2022. 11. 14. 20:09
import React, {useEffect, useState} from "react";
import { dbService } from "Fbase";
import { addDoc, collection, onSnapshot, query, orderBy } from "firebase/firestore";
import {Zweet} from "components/Zweet";

export const Home = ({ userObj })=> {
    const [zweet, setZweet] = useState("");
    const [zweets, setZweets] = useState([]);
    useEffect(()=>{
        const q = query(
            collection(dbService, "zweets"),
            orderBy("createdAt","desc")

        );
        onSnapshot(q, (snapshot)=>{
            const zweetArr = snapshot.docs.map((doc)=>({
                id: doc.id,
            ...doc.data(),
            }));
            setZweets(zweetArr);
        });
    },[]);

( dbService = getFirestore , Zweet = "서브밋시 마운트 될 컴포넌트"

userObj = "firebase.auth().onAuthStateChanged 에서 받아온 유저오브젝트" )

 

리액트라우터를 이용할 Router.js 컴포넌트에

 

메인화면 컴포넌트(Home)를 글을 업로드시 실시간기능을 넣는다고 가정했을때

 

위와 같이 유스이팩트를 통해서 쿼리를 만들고 업로드 될 요소의 순서를 지정해준다.

 

createdAt는 시간별로 나올 것이고 desc를 설정하였기 때문에 현재와 가까운

 

시간일수록 위로 업로드 된다.

 

onSnapshot을 사용하여서 본격적으로 실시간 기능을 구현시킨다.

 

onSnapshot은 데이터베이스에 변화가 생겼을 경우 알려주는 리스너 역할이다.

 

map을 통해서 각각 id와 data()의 리터럴을 가진 요소가 실시간으로 업로드 된다.

 

 

const onSubmit = async (event)=> {
    event.preventDefault();
    try{
        const docRef = await addDoc(collection(dbService, "zweets"),{
            text: zweet,
            createdAt: Date.now(),
            creatorId: userObj.uid,
        });
        console.log("Document written with ID: ",docRef);
    } catch (error) {
        console.error("Error adding document: ", error);
    }
    setZweet("");
};

글을 업로드 했을때(submit 했을때) 실행되는 함수이다.

 

서브밋 됐을때 새로고침기능을 없앤 후 async를 사용하여 try와 catch로 성공/실패 했을때

 

지정해둔 함수를 반환하도록 만든다.

 

addDoc기능을 임포트해서 사용했으므로 새로운 Document(문서)를만들어서

 

text, createdAt, creatorId 의 리터럴을 만들어 준다.

 

마지막으로 setZweet을 빈문자열로 만들어줘서 글쓰는 인풋을 초기화 시켜준다.

 

 

const onChange = ({ target: {value} })=> {
    setZweet(value);
}

업로드할 input 내의 리스너를 만들어줘서 즉각 랜더링될 수 있도록 만든다.

 

 

        return (
            <div>
                <form onSubmit={onSubmit}>
                    <input
                        value={zweet}
                        onChange={onChange}
                        type="text"
                        placeholder="What's on your mind?"
                        maxLength={120}
                    />
                    <input type="submit" value="zweet"/>
                </form>
                <div>
                    {zweets.map(zweet => (
                        <Zweet key={zweet.id} zweetObj={zweet}
                        isOwner={zweet.creatorId === userObj.uid }/>
                    ))}
                </div>
            </div>
        );
};

isOwner 속성은 댓글작성자만 글을 삭제할 수 있도록 하기 위해 가져온 속성이다.

2022. 11. 12. 22:07

Firebase 설치시 npm i firebase 를 하면 최신버전이 인스톨된다.

 

npm i firebase@9.14.0 이와 같이 입력하면 버전 9.14.0으로 사용가능 하다.

 

create-react-app 을 사용했을 때 의 기준으로 작성되었다.

 

 

# 사용예시

import firebase from "firebase/compat/app";
import "firebase/compat/auth";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
    apiKey: process.env.REACT_APP_API_KEY,
    authDomain: process.env.REACT_APP_AUTH_DOMAIN,
    projectId: process.env.REACT_APP_PROJECT_ID,
    storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_MESSAGIN_ID,
    appId: process.env.REACT_APP_APP_ID,
};

firebase.initializeApp(firebaseConfig);

export const authService = firebase.auth();
export const dbService = getFirestore();

나의 경우 Fbase.js 라는 js파일을 만들어 주고 사용하고자하는 기능들을 임포트 시킨 후 따로 변수를 지정해주어서

export 해서 필요한 컴포넌트에서 임포트 시켜서 사용하고 있다.

 

 

# Absolute Imports 경로 src고정하는 기능 ( 부가기능 )

import 경로의 경우 Absolute Imports를 사용하고 있기 때문에 초기경로가 모두 src폴더에서 시작한다.

장점으로는 가독성이 좋고, 경로를 직관적으로 볼 수 있어 경로오류를 줄여주므로 작업 속도를 늘려 줄 수 있다.

적용 방법은 src폴더 위치와 동일한 위치에 jsconfig.json 파일을 만들어서 https://create-react-app.dev/docs/importing-a-component/

링크를 통해 Absolute Imports의 코드블럭 내용을 복사하여 해당 파일에 붙여넣기하면 된다.

 

# Fire Base 프로젝트 만들기

파이어베이스 웹사이트에 접속하여 새로운 프로젝트를 만들고자 하는 앱 혹은 웹을 선택하여 생성한다.

이 후 코드블럭에 Firebase configuration 부분을 복사해서 Fbase.js에 붙여넣기 한다.

const firebaseConfig = {
    apiKey: This0is0the0key,
    authDomain: project-111.firebaseapp.com,
    projectId: project-111,
    storageBucket: project-111.appspot.com,
    messagingSenderId: 112114119000,
    appId: 10:3.1415926535:web:a1b1c2d615s6s1s5,
};

위와 같이 오브젝트 리터럴을 가지게 되는데 이 config key들이 노출되면 누구나 해당 키를 연결하여 데이터 베이스를 만질 수 있게 된다.

깃허브에 푸쉬하여 공유할 경우 암호화를 시킬 필요가 있어보인다.

 

# config key 깃허브 푸쉬로부터 암호화 시키기

.gitignore 의 위치와 같은 위치에 .env 파일을 만든 후 아래와 같이 변수를 만들어 준 후 Firebase에서 받은 config key들을 할당해준다.

REACT_APP_API_KEY=This0is0the0key
REACT_APP_AUTH_DOMAIN=project-111.firebaseapp.com
REACT_APP_PROJECT_ID=project-111
REACT_APP_STORAGE_BUCKET=project-111.appspot.com
REACT_APP_MESSAGIN_ID=112114119000
REACT_APP_APP_ID=10:3.1415926535:web:a1b1c2d615s6s1s5

위와 같이 create-react-app에서는 환경변수를 사용할때 REACT_APP_***_*** 이런식으로 변수명을 지정해주어야 적용된다.

지키지 않을경우 절대로 할당값은 적용되지 않는다.

 

이 후에 .gitignore 파일을 열어서 # misc 주석이 달려있는 가장 밑 부분에 .env를 추가해주면 .env는 푸쉬에서 제외된다.

( 웹스톰의 경우 리베이스를 해주어야 된다. )

 

const firebaseConfig = {
    apiKey: process.env.REACT_APP_API_KEY,
    authDomain: process.env.REACT_APP_AUTH_DOMAIN,
    projectId: process.env.REACT_APP_PROJECT_ID,
    storageBucket: process.env.REACT_APP_STORAGE_BUCKET,
    messagingSenderId: process.env.REACT_APP_MESSAGIN_ID,
    appId: process.env.REACT_APP_APP_ID,
};

이 후 process.env.변수명 을 입력해주어서 암호화 한다.

2022. 11. 12. 20:39

# useNotification의 기능

 

const useNotification = (title, options) => {
    if (!("Notification" in window)) {
        return;
    }
    const fireNotif = () => {
        if (Notification.permission !== "granted") {
            Notification.requestPermission().then((permission) => {
                if (permission === "granted") {
                    new Notification(title, options);
                } else {
                    return;
                }
            });
        } else {
            new Notification(title, options);
        }
    };
    return fireNotif;
};

useNotification은 알림기능을 사용할때 쓰는 hook이다.

 

반환값은 fireNotif를 반환한다.

 

fireNotif는 운영체제 내에서 알림설정이 허용 되었을때만 실행된다.

 

useNotification의 첫번째 인자는 알림의 타이틀을 전달받고

 

두번째 인자는 옵션으로, Notification의 API웹사이트에서 확인해 볼 수 있다.

https://developer.mozilla.org/ko/docs/Web/API/Notification

( 사용예시로는 { body: "적고싶은 내용" } 옵션을 사용할 예정이다. )

 

 

# 설명

 

if (!("Notification" in window)) {
    return;
}

웹의 경우에만 알림이 뜨도록 설정한다.

 

 

const fireNotif = () => {
    if (Notification.permission !== "granted") {
        Notification.requestPermission().then((permission) => {
            if (permission === "granted") {
                new Notification(title, options);
            } else {
                return;
            }
        });
    } else {
        new Notification(title, options);
    }
};
return fireNotif;

권한이 허용되지 않았을때 권한획득을 요청한다.

 

Notification.requestPermission().then() 은 권한을 획득하기 위한 구문이다.

 

이 후 권한이 허용 되었다면 new Notification(title, options)를 통해서 알림을 띄우고

 

허용하지 않게되면 return하여 브레이크를 건다.

 

애초에 허용되어있다면 바로 알림을 띄운다.

 

 

# 사용예시

 

const triggerNotif = useNotification("Can I steal your kimch?", {
   body: "I love kimch dont you"
});

 <button onClick={triggerNotif}>hello</button>

triggerNotif변수를 선언해서 useNotification을 할당해주고 매게변수에 각각 타이틀과 옵션을 넣어준다.

 

이 후 버튼요소에 onClick이벤트를 넣어주고 triggerNotif를 할당해주어서 클릭시 Notification기능을 실행시킨다.

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

[ React Hook ] 10. useAxios  (0) 2022.11.16
[ React Hook ] 8. useFullscreen  (0) 2022.11.09
[ React Hook ] 7. useFadeIn  (0) 2022.11.05
[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
2022. 11. 9. 22:48

# useFullscreen의 기능

 

import {useRef} from "react";

export const useFullscreen = (callback) => {
    const element = useRef();
    const runCd = (isFull) => {
        if (callback && typeof callback === "function") {
            callback(isFull);
        }
    };
    const triggerFull = () => {
        const El_Curt = element.current;
        if (El_Curt) {
            if (El_Curt.requestFullscreen) {
                El_Curt.requestFullscreen();
            } else if (El_Curt.MozRequestFullscreen) {
                El_Curt.MozRequestFullscreen();
            } else if (El_Curt.webkitRequestFullscreen) {
                El_Curt.webkitRequestFullscreen();
            } else if (El_Curt.msRequestFullscreen) {
                El_Curt.msRequestFullscreen();
            }
            runCd(true);
        }
    };
    const exitFull = () => {
        if (document.exitFullscreen) {
            document.exitFullscreen();
        } else if (document.MozCancelFullscreen) {
            document.MozCancelFullscreen();
        } else if (document.webkitExitFullscreen) {
            document.webkitExitFullscreen();
        } else if (document.msExitFullscreen) {
            document.msExitFullscreen();
        }
        runCd(false);
    };
    return { element, triggerFull, exitFull };
};

useFullscreen은 등록한 이미지를 전체화면모드로 전환할 수 있도록 이벤트를 추가해주는 hook이다.

 

반환값은 { element, triggerFull, exitFull }를 반환한다.

 

triggerFull은 전체화면 이벤트를 추가해주는 함수이고

 

exitFull는 전체화면이벤트를 취소해주는 기능을 가진 함수이다.

 

element는 useFullscreen을 사용할 컴포넌트요소에 ref 속성으로 접근하기 위한 값이다.(useRef를 사용한 이유)

 

 

# 설명

 

const element = useRef();

element라는 변수는 컴포넌트에 ref속성으로 접근하기 위해서 useRef를 사용하여 반환값으로 둔다.

 

 

const runCd = (isFull) => {
    if (callback && typeof callback === "function") {
        callback(isFull);
    }
};

 

useFullscreen의 매개변수가 true(존재하고)이고 코드의 타입이 함수인경우,

 

useFullscreen의 매개변수로 들어간 함수(callback)의 매개변수가 runCd의 매게변수로 전달된다는 뜻이다.

 

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

< 간단한 예시 >

 

const Hi = (event) => { console.log( event ? "Hi" : "I can't say Hi" ) };

 

... useFullscreen(Hi);

 

runCd(true);

 

결과로는 runCd의 매개변수는 true이므로  useFullscreen의 매개변수로 들어간 Hi함수의 매개변수

event는 트루값을 전달받게 되므로 콘솔로그는 "HI" 가 반환된다.

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

 

 

const triggerFull = () => {
    const El_Curt = element.current;
    if (El_Curt) {
        if (El_Curt.requestFullscreen) {
            El_Curt.requestFullscreen();
        } else if (El_Curt.MozRequestFullscreen) {
            El_Curt.MozRequestFullscreen();
        } else if (El_Curt.webkitRequestFullscreen) {
            El_Curt.webkitRequestFullscreen();
        } else if (El_Curt.msRequestFullscreen) {
            El_Curt.msRequestFullscreen();
        }
        runCd(true);
    }
};

triggerFull함수는 useRef를 사용해서 current리터럴이 포함되어있는 겨우에 풀스크린 이벤트를 추가해주는 함수이다.

 

El_curt는 ( element.current )를 반복하기 싫기 때문에 변수로 만들어 준 이후 사용한다.

 

else if 를 이용하여 비슷하지만 다른 이벤트를 추가해준 이유는 웹브라우저마다 반응하는 이벤트이름이 다르기 때문이다.

 

Firefox = moz

Opera = webkit

Microsoft (Edge)  =  ms

 

위와 같이 웹브라우저 마다 다를 경우를 대비하여, 추가적으로 조건문을 사용하여 이벤트명을 다양하게 입력해준다.

 

 

const exitFull = () => {
    if (document.exitFullscreen) {
        document.exitFullscreen();
    } else if (document.MozCancelFullscreen) {
        document.MozCancelFullscreen();
    } else if (document.webkitExitFullscreen) {
        document.webkitExitFullscreen();
    } else if (document.msExitFullscreen) {
        document.msExitFullscreen();
    }
    runCd(false);
};

exitFull함수는 triggerFull함수와 반대로 천제화면을 해제하는 이벤트이다.

 

triggerFull함수와 동일하게 웹브라우저마다 적용될 수 있도록 웹사이트에 맞는 각각의 추가적으로 조건문을 만들어준다.

 

 

# 사용예시

 

const onFullS = (isFull) => {
  console.log(isFull ? "We are Full" : "We are Small");
};

const { element, triggerFull, exitFull } = useFullscreen(onFullS);

<div className="App" style={{ height: "1000vh" }}>
    <div ref={element}>
        <img
            src="https://p4.wallpaperbetter.com/wallpaper/817/916/889/falcon-9-rocket-4k-high-definition-wallpaper-preview.jpg"
            alt="Picture"
        />
        <button onClick={exitFull}>Exit fullscreen</button>
    </div>
    <button onClick={triggerFull}>Make fullscreen</button>
</div>

onFulls는 전체화면이 활성화, 비활성화되었을 때  runCd를 통해서 매개변수에 true와 false를 전달받기때문에

 

onFulls의 매개변수isFull을 넣어서 조건문을 만들어준다.

 

구조분해할당을 사용하여서 useFullscreen의 반환값인 element, triggerFull, exitFull을 가져와서 컴포넌트에 넣어준다.

 

전체화면 이벤트를 실행시킬 컴포넌트요소 속성에 ref={element} 를 넣어서 이벤트를 실행할 수 있는 상태로 만들어준다.

 

이후 버튼에 각각 exitFull함수와 triggerFull함수를 넣어줘서 활성화, 비활성화 할 수 있는 버튼을 만들어준다.

( exitFull버튼은 ref-{elemet} 요소 안에 자식요소로 존재함으로 전체화면 상태일때도 img요소 밑에 존재한다. )

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

[ React Hook ] 10. useAxios  (0) 2022.11.16
[ React Hook ] 9. useNotification  (0) 2022.11.12
[ React Hook ] 7. useFadeIn  (0) 2022.11.05
[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
2022. 11. 5. 22:06

# useFadeIn의 기능

 

import {useEffect, useRef} from "react";

export const useFadeIn = (duration = 1, delay = 0) => {
    if (typeof duration !== "number" || typeof delay !== "number") {
        return;
    }

    const element = useRef();

    useEffect(() => {
        if (element.current) {
            const { current } = element;
            current.style.transition = `opacity ${duration}s ease-in-out ${delay}s`;
            current.style.opacity = 1;
        }
    }, []);
    return { ref: element, style: { opacity: 0 } };
};

useFadeIn은 opacity를 사용하여 서서히 나타나는 기능을 사용할때 쓰는 hook이다.


반환값은 { ref: element, style: { opacity: 0 } } 을 반환한다.

 

즉 style.opacity를 통해서 투명도에 접근할 수 있게 만들어 준다.

 

 

# 설명

 

if (typeof duration !== "number" || typeof delay !== "number") {
    return;
}

우선 가장먼저 첫번째 전달인자(duration)와 두번째 전달인자(delay)가 숫자인지 확인하여 유효성 검사를 한다.

 

 

const element = useRef();

이 후에 element라는 변수를 선언해주고 useRef()를 할당해주고 임포트 시켜준다.( import {useRef} from "react" )

 

useRef로 인해 element는 ref(refenrence)속성으로 접근 가능하게 된다.

ex) <div ref={element} > hi </div>

 

그리고 useRef가 할당된 변수에는 current라는 속성이 추가되고, 이는 할당된 변수의 속성 전체를 감싸는 속성이 된다.

 

 

	useEffect(() => {
        if (element.current) {
            const { current } = element;
            current.style.transition = `opacity ${duration}s ease-in-out ${delay}s`;
            current.style.opacity = 1;
        }
    }, []);
    return { ref: element, style: { opacity: 0 } };

useEffect를 사용해서 ( element.current )가 true일때 = ( useRef가 할당된 변수일때 ) 함수를 실행하도록 만든다.

 

구조분해할당을 사용하여 element에서 current 속성을 가져온 후에 스타일에 접근하여

 

transition과 opacity를 변경할 수 있도록 구성해준다.

 

useFadeIn의 반환값은 ref: element , style: { opacity: 0 } 의 속성을 반환한다.

 

 

# 사용예시

 

 const fadeInH1 = useFadeIn(1, 2);
 const fadeInP = useFadeIn(5, 10);

 <h1 {...fadeInH1}>hello</h1>
 <p {...fadeInP}>holly sheet</p>

fadeInH1과 fadeInP를 선언해서 각각 h1,p 시멘틱테그에 적용할 수 있도록 만들어 준다.

 

useFadeIn의 첫번째 전달인자는 duration이고 두번째 전달인자는 delay이다.

 

속성(attribute)에 보면 { ...변수명 } 으로 해준 부분은 결과적으로 변수에 할당된 값을 적용(가져온다)시킨다는 뜻이다.

 

그렇게 되면 useFadeIn의 반환값인 { ref: element, style: { opacity: 0 } }를 가져오게 되고

 

각 전달인자에서 받은 값들이 적용된 결과를 보여주게 된다.

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

[ React Hook ] 9. useNotification  (0) 2022.11.12
[ React Hook ] 8. useFullscreen  (0) 2022.11.09
[ React Hook ] 6. useScroll  (0) 2022.11.04
[ React Hook ] 5. useNetwork  (0) 2022.11.03
[ React Hook ] 4. usePreventLeave  (0) 2022.11.02
2022. 11. 4. 22:15

# useScroll의 기능

 

import {useEffect, useState} from "react";

export const useScroll = () => {
    const [state, setState] = useState({
        x: 0,
        y: 0
    });
    const onScroll = () => {
        setState({ y: window.scrollY, x: window.screenX });
    };
    useEffect(() => {
        window.addEventListener("scroll", onScroll);
        return () => window.removeEventListener("scroll", onScroll);
    }, []);
    return state;
};

useScroll은 스크롤의 위치를 감지하여 확인할 수 있는 hook이다.


반환값은 { x : 0(위치) , y : 0(위치) }로 각 스크롤의 x와 y값을 반환한다.

 

 

# 설명

 

const [state, setState] = useState({
    x: 0,
    y: 0
});

 

useState를 사용해서 객체리터럴 x와 y를 만들고 x에는 x좌표의 스크롤위치와

 

y에는 y좌표 스크롤 위치를 불러올 것이다.

 

 

const onScroll = () => {
    setState({ y: window.scrollY, x: window.screenX });
};

onScroll함수를 만들어주고 setState에 y = y스크롤위치, x = x스크롤위치를 넣어주는 기능을 넣어준다.

 

 

useEffect(() => {
    window.addEventListener("scroll", onScroll);
    return () => window.removeEventListener("scroll", onScroll);
}, []);
return state;

useEffect를 사용하여 이벤트 리스너를 걸어준다.

 

window에서 스크롤되면 onScroll함수를 실행시킨다.

 

스크롤이 될때마다 onScroll가 실행되고 onScroll 내부에서는 setState를 변환시켜주기 때문에

 

state의 값을 계속해서 re-render를 시켜준다.

 

그리고 컴포넌트가 보이지 않을때는 이벤트를 삭제 해준다.

 

 

# 사용예시

 

 const { y } = useScroll();

 <div className="App" style={{ height: "1000vh" }}>
     <h1 style={{ position: "fixed", color: y > 100 ? "red" : "blue" }}>hi</h1>
 </div>

구조분해할당을 사용하여 useScroll에서 y를 가져온다.

 

이 후에 style.color에 y가 100보다 크면 "red" 색상이 되고, 적으면 "blue"색상이 되도록 만들었다.

 

결과 : 스크롤을 내리면 red가 되고 가장위로 올리면 blue가 된다.

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

[ React Hook ] 8. useFullscreen  (0) 2022.11.09
[ React Hook ] 7. useFadeIn  (0) 2022.11.05
[ React Hook ] 5. useNetwork  (0) 2022.11.03
[ React Hook ] 4. usePreventLeave  (0) 2022.11.02
[ React Hook ] 3. useTabs  (0) 2022.10.31
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