React Hooks은 리액트의 새로운 기능으로 React 16.8버전에 새로 추가된 기능이다.
Basic Hooks
- useState
- useEffect
- useContext
Additional Hooks
- useReducer
- useCallback
- useMemo
- useRef
- useImperativeHandle
- useLayoutEffect
- useDebugValue
value만 배열로 return : const [value] = useFetch('/api/something');
value만 Object로 return : const {value} = useFetch('/api/something');
app.js
class App extends Component {
state = {
count : 0
};
modify = n => {
this.setState({
count : n
});
};
render(){
const {count} = this.state;
return(
<>
<div>{count}</div>
<button onClick={()=> this.modify(count +1)}>Increment</button>
</>
)
}
}
위에 코드를 보다시피 Class component
가 필요하고 state
도 필요하고 그걸 정의해야 하고 패스 해야하는 등등 많은 것들을 하게 되는 단점을 가지고 있다.
app.js
const App = ()=>{
const [count, setCount] = useState(0);
return(
<>
<button onClick = {()=>setCount(count + 1)}>Increment</button>
</>
)
}
React Hook을 사용하면 더 이상 class를 사용하지 않고 모든것이 함수형 프로그래밍을 할 수 있다.
React Hook의 좋은 점은 함수형 프로그래밍을 지원하는 것이다.
app.js
import React, { useState } from "react";
const 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>
);
};
export default App;
app.js
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>
);
}
incremxetitem = ()=>{
this.setState(state => {
return {
item : state.item + 1
};
});
};
decrementItem = ()=>{
this.setState(state => {
return {
item : state.item + 1
};
})
}
};
useInput
hooks는 초기 value값을 셋팅해주고 내부에 onChange
메서드를 사용하여 입력창에 텍스트가 업데이트 될 때 마다 콘솔에 입력해주는 함수를 생성하였다.
import React, { useState } from "react";
const useInput = (initialValue) => {
const [value, setValue] = useState(initialValue);
const onChange = (event) => {
console.log(event.target);
};
return {
value,
onChange
};
};
const App = () => {
const name = useInput("Mr.");
return (
<div className="App">
<h1>Hello</h1>
<input placeholder="Name" {...name} />
//주요 구문 전개연산자 & 디스트럭쳐의 조합
</div>
);
};
export default App;
위 코드는 App component가 아니라 완전히 다른 function에서 이벤트를 처리할 수 있다.
결론
우리의 이벤트를 분리된 파일, 다른 entitiy에 연결해서 처리할 수 있다.
유효성 검사
코드를 살펴 보기 전 확인해야 될 문법)
const [value, setValue] = useState(initialValue);
const onChange = (event)=> {
const {
target : { value }
} = event;
// = `const value = event.target.value;` 위에 있는 코드와 같은 코드이다.
...
}
name
변수에 할당된 값은 useInput 값의 리턴값인 value
,onChange
이다. input의 속성으로 value
와 onChange
가 존재하므로 전개연산자를 사용하여 쉽게 만들어 줄 수 있다.const useInput = (initialValue, validator)=>{
...
return {
value,
onChange
}
}
const App = ()=> {
const name = useInput("Mr.", maxLen);
return(
<input placeholder="Name" {...name} />
)
}
app.js
import React, { useState } from "react";
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);
}
console.log(value);
};
return {
value,
onChange
};
};
const App = () => {
//inpu에 10이하 문자열만 입력되게 하기
const maxLen = (value) => value.length <= 10;
const name = useInput("Mr.", maxLen);
return (
<div className="App">
<h1>Hello</h1>
<input placeholder="Name" {...name} />
</div>
);
};
export default App;
import { 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
};
};
const App = () => {
const {currentItem, changeItem} = useTabs(1, content);
console.log(currentItem,changeItem)
return (
<div className ="App">
{
content.map((section, index)=>{
return(
<button onClick={()=> changeItem(index)}>{section.tab}</button>
)
})
}
<div>{currentItem.content}</div>
</div>
);
}
export default App;
Promise Fetch hook
useFetch.js
import { useEffect, useState } from "react";
export default function useFetch(url) {
const [data, setData] = useState([]);
useEffect(() => {
fetch(url)
.then(res => {
return res.json();
})
.then(data => {
setData(data);
});
}, [url]);
return data;
}
사용
Day.jsx
import useFetch from "../hooks/useFetch";
import { useParams } from "react-router-dom";
export default function Day(){
const {day} = useParams();
const words = useFetch(`http://localhost:3001/words?day=${day}`);
return(
<>
...
</>
)
}