JSX
JSX란 Javascript가 조금 더 확장된 문법이다.
React에서 JSX의 사용은 필수적이지 않다고 말하지만 실질적으로 React를 사용할 때 JSX를 사용한다는 것은 너무나 매력적인 일이다. 특히나 React안에서 javascript를 이용한 UI적인 요소를 관리하고 생성할 때 JSX를 쓴다면 그것은 훨씬 시각적인 일이 되고 편한 코드 생성을 도와줄 것이다.
JSX의 코드 생성은 다음과 같은 형태를 띤다.
const element = <div>Hello! React</div>
위의 코드는 기존의 javascript도 아니며 HTML도 아니다.
또한 다음과 같이 중괄호로 묶어 변수를 사용할 수 도 있다.
const name = 'Henry Noh';
const element = <div>Hello {name}</div>;
또한 JSX는 컴파일이 끝난 후에 Javascript 함수가 호출되며 기존의 Javascript 객체로 인식하게 된다.
따라서 다음과 같은 문법을 사용할 수 있게 된다.
const getGreeting = (user) => {
if (user) {
return <h1>Hello, {formatName(user)}!</h1>;
}
return <h1>Hello, Stranger.</h1>;
}
실제로 React에서 코드를 작성할 때 component의 속성 값을 변경시켜주기 위하여 우리는 camelCase를 사용하게 되는데 이러한 camelCase를 따르는 규칙 또한 JSX의 문법이다!
const element = <div tabIndex="0"></div>;
Hook
React 16.8 버전 이후로 도입된 hook은 더 이상 우리가 LifeCycle을 관리하며 react를 작성할 필요가 없게 만들어 주었다.
그렇다고 LifeCycle이 사라졌다는 것이 아니라 그와 같은 react의 개념을 좀 더 직관적으로 사용할 수 있게 주어지는 API인 것이다.
이제는 더 이상 React에서 조차 class형 컴포넌트가 아닌 functional 컴포넌트를 사용할 것을 추천하기 때문에 class 방식으로 사용하는 것이 필요로 하지 않게 되었다. 하지만 그 뜻이 class 방식을 아예 몰라도 된다는 뜻은 아니다. hook이 나온 이후로 hook을 이용한 functinal 컴포넌트는 이 세상에 존재하는 모든 class형 컴포넌트와 같이 쓸 수 있도록 만들었으며 (class형 컴포넌트 내부에서 사용은 불가능) 실질적으로 새로 작성하는 코드가 아닌 이상 우리는 엄청나게 많은 class형 컴포넌트를 관리하게 될 것이다.
따라서 왜 Hook이 나오게 된 것이며 LifeCycle Method와 같고 다른 점이 무엇인지 파악해야 할 필요성이 있다.
(추후에 작성 예정)
Hook이 나오게 된 이유는 다음과 같다.
- LifeCycle을 사용하던 방식의 기존 class형 컴포넌트는 각 method에 필요하지 않은 로직이 섞여있을 때가 있다.
- componentDidMount와 componentDidUpdate는 컴포넌트 안에서 데이터를 가져오는 작업을 수행하기 위하여 만든 method이지만 componentDidUpdate에서 이벤트 리스너를 설정하는 것과 같은 관계없는 로직이 포함되기도 한다.
- componentWillUnmount에서 cleanup과 같은 로직을 수행하기도 한다.
- 상태 관련 로직은 한 컴포넌트를 작은 단위로 분해하기 힘들게 만든다.
- Class는 사람과 기계를 헷갈리게 만든다.
- React에서 class형 컴포넌트를 사용하기 위해서는 this를 명확하게 알아야만 한다. 하지만 JS의 this는 다른 언어들과는 다르게 그 의미와 용도를 정확하게 파악해야만 잘 사용할 수 있다.
아마 React를 사용하면서 가장 많이 사용하게 될 hook은 2가지 정도가 있을 것이다.
useState
1. 초기값은 1번만! 변경은 언제나 set함수
const [*name*, set*Name*] = useState(*initial property*);
name은 내 마음대로 정할 수 있다. 다만 뒤의 name값을 변경시켜주는 함수는 언제나 setName으로 정해야 한다.
initial property는 컴포넌트의 렌더링이 시작된 순간 단 1번만 사용된다.
2. initial property는 원하는 대로
initial property에 들어가는 값은 변수도 될 수 있고 객체도 될 수 있고 배열도 될 수 있다.
const [count,setCount] = useState(0);
const [name,setName] = usestate('Henry Noh');
const [array,setArray] = useState([{name:'henry'}]);
3. 수정은 다음과 같이
import React, {useState} from 'react';
const App = () => {
const [count,setCount] = useState(0);
const [name,setName] = useState('Henry Noh');
const [obj,setObj] = useState({name:'Henry'});
//count 변경
const onChangeCount = () => {
setCount(1);
};
//name 변경
const onChangeName = () => {
setName("Michael");
};
//객체 변경
const onChangeObj = (e) => {
const name = e.target.name;
setObj({
...obj,
[name] : 'test',
})
};
return (
<>
<button onClick = {onChangeCount}>button</button>
<button onClick = {onChangeName}>button</button>
<button onClick = {onChangeObj} name="name">button</button>
<div>{count}</div>
<div>{name}</div>
<div>{obj.name}</div>
</>
)
};
export default App;
useEffect
react 공식 document에 따르면 useEffect를 LifeCycle method의 componentDidMount, componentDidUpdate, componentWillUnmount를 합친 것으로 생각해도 좋다고 말하고 있다.
또한 useEffect 그 자체는 useEffect hook안에 정의된 함수 그 자체를 기억했다가 해당 컴포넌트에 대한 DOM의 업데이트가 이루어진 이후에 그 기능을 수행한다. 즉 해당 컴포넌트가 렌더링이 된 이후에 함수를 실행한다는 뜻이다. 이러한 방식의 동작은 component안에 있는 데이터, 변수를 document 그 자체 내에서 언제든지 자유롭게 사용할 수 있게 된다는 것이다.
import React, {useState, useEffect} from 'react';
const App = () => {
const [count,setCount] = useState(0);
//count 변경
const onChangeCount = () => {
setCount(1);
};
useEffect(()=>{
document.title = `You Clicked ${count} times`;
})
return (
<>
<button onClick = {onChangeCount}>button</button>
<div>{count}</div>
</>
)
};
export default App;
이외에도 useContext, useReducer, useCallback, useMemo, useRef와 사용자 정의 Hook을 만들 수 있다.
댓글