항상 2개의 value를 return함
첫번째 value를 item이라고 이름을 주고, 두번째 value는 값을 변경하게 함
const [counter, setCounter] = React.useState(0);
const onClick = () => {
setCounter(counter + 1);
};
데이터를 숫자형 데이터로 건네줄거고, 그 데이터 값을 바꿀 함수도 함께 줄거임. 그리고 그 함수를 이용해서 데이터를 바꿨을 때, 데이터 값이 바뀌고 컴포넌트도 동시에 리렌더링될 거임! 업데이트가 완료되는 것!
Q. 왜 useState는 let이 아니라 const를 사용할까 ?
정확하게 새로운 값을 부여하는게 아니기 때문! useState는 단순히 상태를 업데이트하는 함수이다!
spread operator(스프레드 연산자)
https://www.techiediaries.com/react-spread-operator-props-setstate/
■ value={name.value} onChange.{name.onChange} 은
{...name} 과 같은 의미
안에 있는 모든 것을 un
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};
};
import "./styles.css";
import React, { useState } from "react";
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 useTabs = (initialTab, allTabs) => {
const [currentIndex, setcurrentIndex] = useState(initialTab);
if (!allTabs || !Array.isArray(allTabs)) {
return;
}
return { currentItem: allTabs[currentIndex], changeItem: setcurrentIndex// state를 업데이트 시키는거니까 };
};
const App = () => {
const { currentItem, changeItem } = useTabs(0, content);
return (
<div className="App">
{content.map((section, index) => (
<button onClick={() => changeItem(index)}>{section.tab}</button>
))}
<div>{currentItem.content}</div>
</div>
);
};
export default App;
setstate는 rerendering 해주는거
가끔은 특정 코드의 실행을 제한하고 싶다.
component가 맨 처음 render될 때만 말야!
그리고는 다시 실행 ㄴㄴ
useEffect는 두 개의 argument를 가지는 function
첫번째 argument는 우리가 딱 한번만 실행하고 싶은 코드가 될거임 - function으로써의 effect
두번째 argument는 정말 마법같은 친구 - deps(필수 ㄴ), deps list에 있는 값일 때만 값이 변하도록 활성화 될거임
useEffect function은 쉽게 말해서 우리 코드가 딱 한번만 실행될 수 있도록 보호해줘
useEffect(() => {
console.log("CALL THE API....");
}, []);
어떤 일이 일어나도 이 코드는 딱 한 번만!
deps
useEffect(() => {
console.log("I run when 'keyword' changes.");
}, [keyword]);
keyword가 변화할 때 코드를 실행하고 싶다면, 이 자리에 'keyword'라고 써줘.
여기서 하는 건 이 keyword가 변화할 때 코드를 실행할거라고 react.js에게 알려주는거야.
그래서 이 코드는 keyword가 변화할 때만 실행될거임
useEffect(() => {
console.log("I run only once.");
}, []);
이게 바로 우리가 여기에 빈 array를 써 주었을 때 코드가 단 한번만 실행되는 이유임
ex) useEffect(sayHello, [number]);
useEffect가 sayHello를 component가 mount 되었을 때 실행시켰고, 그리고 number가 바뀔때만 실행됨
useEffect 왜 써?
렌더링이 계속 된다면, 특히 특정 api를 불러오게 되는 경우 계속해서 불러오는 문제가 생길 수 있음!
state를 변경할 때, 계속해서 렌더링 되는 문제점이 존재함.
많은 state가 존재한다면 성능 저하 문제가 발생할 있기에 이런 문제를 해결하기 위해 사용함!
const useTitle = (initialTitle) => {
const[title,setTitle] = useState(initialTitle);
const updateTitle = () => {
const htmlTitle= document.querySelecotr("title");
htmlTitle.innerText = title;
};
useEffect(updateTitle, [title]);
return setTitle;
}
const App = () => {
const titleUpdater = useTitle("Loading...");
return (
<div className="App">
<div>Hi</div>
</div>
)
};
const useClick = (onClick) => {
const ref = useRef();
useEffect(() => {
const element = ref;
if (element.current) {
element.current.addEventListener("click", onClick);
}
return () => {
if (element.current) {
element.current.removeEventListener("click", onClick);
}
};
}, []);
if (typeof onclick !== "object") {
return;
}
return ref;
};
export default function App() {
const sayHello = () => console.log("sayHello");
const title = useClick(sayHello);
return (
);
}
componentWillMount
: element 의 click 이벤트 없애줌
componentDidMount
click 이벤트 등록 'sayHello'
[] 의사용
dependency 에 아무것도 들어가있지 않음 => 페이지가 redering 될 때 한 번만 동작
const useConfirm = (message="",callback)=> {
if(typeof callback !== "function"){
return;}
const confirmAction = () => {
if(confirm(message)){
callback();
}
}
return confirmAction;
};
const App = () => {
const deleteWorld = () => console.log("Deleting the world");
const abort = () => console.log("Aborted"); //취소
const confirmDelete = useConfirm("Are you sure", deleteWorld);
return (
<div clasName="App">
<button onclick={confirmDelete}>Delete the world</button>
</div>
);
};
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>;
};
const useBeorLeave = onBefore => {
if(typeof onBefore !=="function"){
return;
}
const handle = (event) => {
const {clientY} = event;
if(clientY <=0){
onBefore();}
}
};
useEffect(()=>{
document.addEventListener("mouseleave",handle);
return () => document.removeEventListener("mouseleave", handle)
},[]);
};
const App = () => {
const beForLife = () => console.log("Pls dont leave");
useBeforeLeave(beFor)
return (
<div> className="App">
<h1>Hello</h1>
</div>
);
};
const useNotification = (title, options) => {
if(!("Notification" in window)){
return;
}
const firNotif = () => {
if(Notification.permission !=="granted") {Notification.requestPermission().then(permission=> if(permision==="granted"){
new Notification(title,options);
}else{
return;}
});
}else{
new Notification(title,options);}
};
return firNotif;
};
const App = () => {
const triggerNotif = useNotification("Can I steal your food?")
return (
<div className="App" style = {{ height:"1000vh"}}>
<button onClick={triggerNotif}>Hello</button>
</div>
)
}