**Function component에서 state를 가질 수 있게 해줌**
→ 함수형 프로그래밍(functional programming) 스타일이 됨
react의 state machine에 연결하는 기본적인 방법
react에서 불편했던 점
useEffect(function, [depth]);
return값은 뒷정리 함수로 업데이트되기 바로 직전에 호출됨
조회하는 state나 props가 있다면 depth 배열에 넣어야 한다.
const [item, setItem] = useState(1);
hooks가 생기기 전에 우리는 state를 function component에 사용할 수 없었다.
우리가 state를 가지고 작업을 하고 싶으면 Class Component 형태로 만들어야 했다.
Class component는 this와 같은 문장 규칙과 Render와 같은 사용법을 고려해야 하지만 hook은 그딴거없음
import React, { useState } from "react";
import "./styles.css";
export default function App() {
const [item, setItem] = useState(1);
const incrementItem = () => setItem(item + 1);
const decrementItem = () => setItem(item - 1);
return (
<div className="App">
<h1>Hello {item}</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={incrementItem}>Increment</button>
<button onClick={decrementItem}>decrement</button>
</div>
);
}
class AppUgly extends React.Component {
state = {
item: 1
};
render() {
const { item } = this.state;
return (
<div className="App">
<h1>Hello {item}</h1>
<h2>Start editing to see some magic happen!</h2>
<button onClick={this.incrementItem}>Increment</button>
<button onClick={this.decrementItem}>decrement</button>
</div>
);
}
incrementItem = () => {
this.setState((state) => {
return {
item: state.item + 1
};
});
};
decrementItem = () => {
this.setState((state) => {
return {
item: state.item - 1
};
});
};
}
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const useInput = (initialValue, validator) => {
const [value, setValue] = useState(initialValue);
const onChange = (event) => {
console.log(event.target);
const {
target: { value }
} = event;
let willUpdate = true;
if (typeof validator === "function") {
willUpdate = validator(value);
}
if (willUpdate) {
setValue(value);
}
};
return { value, onChange };
};
export default function App() {
const maxLen = (value) => value.length < 10;
const name = useInput("Mr.", maxLen);
return (
<div className="App">
<h1>Hello</h1>
<input placeholder="Name" {...name} />
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React, { useState } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
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) => {
if (!allTabs || !Array.isArray(allTabs)) {
return;
}
const [currentIndex, setCurrentIndex] = useState(initialTab);
return {
currentItem: allTabs[currentIndex],
changeItem: setCurrentIndex
};
};
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>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.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>Hi</div>
<button onClick={() => setNumber(number + 1)}>{number}</button>
<button onClick={() => setAnumber(anumber + 1)}>{anumber}</button>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React, { useEffect, useState } from "react";
import ReactDOM from "react-dom";
import "./styles.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);
return (
<div className="App">
<div>Hi</div>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React, { useEffect, useState, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const useClick = (onClick) => {
const element = useRef();
useEffect(() => {
if (element.current) { // when **componentDidMount, componentWillUpdate**
element.current.addEventListener("click", onClick);
}
return () => {
if (element.current) { when **componentWillUnmount,**
element.current.removeEventListener("click", onClick);
}
};
}, []);
return element;
};
const App = () => {
const onClick = () => console.log("say hello");
const title = useClick(onClick);
return (
<div className="App">
<h1 ref={title}>Hi</h1>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
export const useHover = onHover => {
if(typeof onHover !== "function"){
return;
}
const element = useRef();
useEffect(() => {
if(element.current){
element.current.addEventListener("mouseenter", onHover);
}
return () => {
if(element.current){
element.current.removeEventListener("mouseenter", onHover);
}
};
}, []);
return element;
};
import React, { useEffect, useState, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const useConfirm = (message = "", callback, rejection) => {
if (callback && typeof callback !== "function") {
return;
}
if(rejection && typeof rejection !== "function"){
return;
}
const confirmAction = () => {
if (confirm(message)) {
callback();
} else {
rejection();
}
};
return confirmAction;
};
const App = () => {
const deleteWorld = () => console.log("Delete World");
const abort = () => console.log("Aborted");
const confirmDelete = useConfirm("Are you sure?", deleteWorld, abort);
return (
<div className="App">
<button onClick={confirmDelete}>Delete the world</button>
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
import React, { useEffect, useState, useRef } from "react";
import ReactDOM from "react-dom";
import "./styles.css";
const usePreventLeave = () => {
const listener = (event) => {
event.preventDefault();
event.returnValue = "";
};
const enablePrevent = () => window.addEventListener("beforeunload", listener);
const disablePrevent = () =>
window.addEventListener("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 rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);