일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- HTML5
- 람다식
- SQL 연산자
- 자바 스프링
- SQL 명령어
- 이클립스
- 노마드코더
- spring
- 환경설정
- numpy
- 오산대맛집
- spring 환경설정
- ubuntu
- Flex Box 기본
- 리액트
- java설치
- SQL
- Eclipse
- SQL 문제
- 자바스프링
- 플랙스박스기본
- 관계형데이터베이스
- Flexbox Froggy
- 타입
- 객체지향프로그래밍
- node.js
- java spring
- REACT
- Hooks
- 스프링
- Today
- Total
이것저것
[Hook]노마드 코더로 hook 공부하기 (2) 본문
https://nomadcoders.co/react-hooks-introduction/lobby
useEffect
useEffect는 생명주기에서 componentWillUnmount와 componentDidMount, componentWillUpdate와 비슷하다.
위의 모든 것과 동일한 function이라고 생각하면 된다.
useEffect는 componentDidMount의 역할을 하기 때문에 새로고침을 하면 먼저 sayHello();가 실행된다.
그리고 componentDidUpdate의 역할도 하기 때문에 클릭을 하면 또 sayHello를 실행한다.
useEffect도 2개의 인자를 받는데 첫 번째는 function으로써의 effect이다.
두 번째 인자는 두번째 인자가 있다면 리스트에 있는 값이 변할 때 활성화된다.
그래서 useEffect의 두 번째 인자 값에 number을 넣어준다면 number가 변할 때마다 hello가 출력된다.(=> version 2)
여기서는 useEffect가 sayHello를 component가 mount 되었을 때 실행을 시켜서
처음에 새로고침을 하면 hello가 출력이 되고 (componentDidMount)
두 번째로 number의 버튼을 누르면 number가 변경되면서 실행이(componentWillUpdate) 된 것이다.
hello를 처음에 한 번만 출력하고 싶다면 [number]를 빈 값으로 []로 변경해주면 어떤 버튼에도 반응하지 않는다.
version1
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const App = () => {
const sayHello =() => console.log("hello");
useEffect(() => {
sayHello();
})
const [number, setNumber] = useState(0);
const [aNumber, setAnumber] = useState(0);
return(
<div className="App">
<div>Hello</div>
<button onClick={()=> setNumber(number + 1)}>{number}</button>
<button onClick={()=> setAnumber(aNumber + 1)}>{aNumber}</button>
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
version 2
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const App = () => {
const sayHello =() => console.log("hello");
const [number, setNumber] = useState(0);
const [aNumber, setAnumber] = useState(0);
useEffect(sayHello, [number])
return(
<div className="App">
<div>Hello</div>
<button onClick={()=> setNumber(number + 1)}>{number}</button>
<button onClick={()=> setAnumber(aNumber + 1)}>{aNumber}</button>
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
useTitle
문서의 제목을(title) 업데이트해줄 수 있는 functional hook이다.
useTitle에 title과 setTitle의 인수를 생성해준다.
titleUpdater는 useTitle에 Loading... 이라는 기본값을 생성해주었다.(titleUpdater는 setTitle과 동일)
useTitle에 useEffect를 사용하기 위해서는 useTitle안에 useEffect를 생성해주면 된다.
useEffect안의 내용은 component가 mount 될 때 updateTitle을 부르고 [title]은 title이 업데이트되면 updateTitle을 다시 부르겠다는 뜻이다.
진행을 설명하자면
처음 페이지가 로딩이 되면 useEffect의 updateTitle은 htmlTitle이 "title"이기 때문에 titleUpdater가 동작하기 전이므로"Loading..." 값을 가지고 있다.
setTimeout이 작동하면 titleUpdater로 title이 변경되므로 useEffect의 [title]에 적용되며 useEffect가 실행된다.
그러면 updateTitle을 다시 부르고 title은 5초 뒤에 Home으로 변경된다.
import React, { useState, useEffect } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const useTitle = (initialTitle) => {
const [title, setTitle] = useState(initialTitle);
const updateTitle = () => {
const htmlTitle = document.querySelector("title");
htmlTitle.innerText = title;
}
useEffect(updateTitle, [title]);
return setTitle;
}
const App = () => {
const titleUpdater = useTitle("Loading...");
setTimeout(() => titleUpdater("Home"), 5000); //5초뒤에 title을 home으로 변경
return(
<div className="App">
<div>Hello</div>
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
useClick
1 ) references란?
useRef는 reference를 사용해 component의 어떤 부분을 선택할 수 있는 방법이다.
document.getElemnetById()와 동등하다.
useRef를 사용해서 input창에 focus가 가게 하는 방법이 있다.
potato.current.focus()를 이용하는 것이다.
potato의 current는 input 태그의 ref이기 때문에 current에 focus()를 주게 되면 input 태그로 포커스를 이동하는 것이다.
import React, { useRef } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const App = () => {
const potato = useRef();
// setTimeout(() => console.log(potato), 4000); //log를 이용해서 potato에 어떤게 입력되는지 확인한다.
setTimeout(() => potato.current.focus(), 4000); //4초뒤에 input창으로 focus가 잡힌다.
return(
<div className="App">
<div>Hello</div>
<input ref={potato} placeholder="1" />
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
2 ) useClick
step1)
우선은 useRef를 이용해서 useClick을 사용할 곳을 정해준다.
element.current는 useRef의 현재 위치인 title이다.
title이 onClick 되었을 때의 이벤트가 생기도록 EventListener를 추가해주었다.
title이 useClick 되었을 때 sayHello가 실행된다.
sayHello는 log에 say Hello를 띄워준다.
그러므로 h1태그의 Hello를 클릭하게 되면 say Hello라는 log가 찍히게 된다.
useEffect는 componentDidMount상태에서 동작한다.
그래서 component가 mount 되었을 때 event를 추가해서 onClick이 실행되게 하였다.
하지만 useEffect는 componentWillUnMount가 될 때 추가해준 event를 정리해줘야 한다.
그래서 step2에서 return에 event를 지워주는 코드를 생성한다.
step2)
함수를 return 해주기 위해서 람다식을 사용했다.
return은 componentWillUnMount일때 실행된다.
dependency값은 [ ]로 빈 값을 줬기 때문에 값이 update 됐을 때를 고려하지 않아도 된다.
dependency가 없으므로 addEventListener는 useEffect의 기능 중 componentDidMount와 componentDidUpdate일때 실행된다.
그리고 removeEventListener는 componentWillUnMount일때 실행이 된다.
eventListener를 return값으로 정리해주는 이유는 component가 mount 되지 않았을 때 componentWillUnMount가 실행되야하는데 return을 해주지 않는다면 addEventListener에서 3가지 라이프사이클이 모두 작동하기 때문이다.
import React, { useState, useEffect, useRef } from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const useClick = (onClick) =>{
const element = useRef();
useEffect(() => {
if(element.current){
element.current.addEventListener("click", onClick);
}
//step2 시작
return () => {
if(element.current){
element.current.removeEventListener("click", onClick)}
}
}, [] );
//step2 끝
return element;
}
const App = () => {
const sayHello = () => console.log("sayHello");
const title = useClick(sayHello);
return(
<div className="App">
<h1 ref={title}>Hello</h1>
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
useConfirm & usePreventLeave
이 두 가지는 실제 hooks가 아니다. useState와 useEffect를 사용하지 않기 때문이다.
1 ) useConfirm
useConfirm은 사용자가 무언가를 하기 전에 확인하는 것이다.
예를 들어 메모를 저장하거나 삭제할 때 browser에서 "정말 수정(삭제)하시겠습니까?"라고 물어보는 alert을 띄워주는 것이다. 그리고 alert창을 닫으면 function이 실행되도록 하는 것이다.
먼저 onConfirm과 onCancle이 존재하는지 확인하는 if문이 2개 있다. onConfirm이 존재하지 않거나 function이 아닐 때 다시 return 한다. onCancle은 동일하다.
생성된 버튼을 누르면 confirmDelete를 부른다.
confirmDelete는 confirmAction이고 confirmAction을 부르면 browser로 가서 true이면 onComfirm이 실행된다.
그리고 delete.... 가 log에 뜨게 된다.
abort는 취소를 눌렀을 때 실행된다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const useConfirm = (message = "", onConfirm, onCancle) => {
if(!onConfirm || typeof onConfirm !== "function"){
return;
}
if(!onCancle || typeof onConfirm !== "function"){
return;
}
const confirmAction = () => {
if(window.confirm(message)){
onConfirm();
} else {
onCancle();
}
}
return confirmAction;
}
const App = () => {
const deleteWorld = () => console.log("delete...."); //확인을 눌렀을때 log출력
const abort = () => console.log("No delete"); //취소를 눌렀을때 log출력
const confirmDelete = useConfirm("Are you sure?", deleteWorld, abort)
return(
<div className="App">
<button onClick={confirmDelete}>Delete the world</button>
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
2 ) usePreventLeave
usePreventLeave는 일반 페이지에서 나가기나 뒤로 가기 버튼을 눌렀을 때 '아직 저장되지 않았습니다'라는 alert창을 띄어주는 것이다.
usePreventLeave도 마찬가지로 hooks를 전혀 쓰지 않는다.
beforeunload는 window가 닫히기 전에 function이 실행되는 것을 허락한다.
인터넷 익스플로러는 안된다. 거의 모든 코드는 확인을 크롬에서 해주는 것이 좋다.
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
const usePreventLeave = () => {
const listener = (event) => {
event.preventDefault();
event.returnValue = "";
}
const enablePrevent = () => window.addEventListener("beforeunload", listener);
const disablePrevent = () =>
window.removeEventListener("beforeunload", listener);
return {enablePrevent, disablePrevent};
}
const App = () => {
const {enablePrevent, disablePrevent} = usePreventLeave();
return(
<div className="App">
<button onClick={enablePrevent}>Protect</button>
<button onClick={disablePrevent}>UnProtect</button>
</div>
)
};
ReactDOM.render(<App />, document.getElementById('root'));
'React를 파고파고 > Hook' 카테고리의 다른 글
[Hook]노마드 코더로 hook 공부하기 (3) (0) | 2020.06.28 |
---|---|
[Hook] 노마드 코더로 hook 공부하기 (1) (0) | 2020.06.25 |