‘React.js’는 SPA 기반의 프론트엔드 개발 프레임워크 중 하나로서, 컴포넌트 단위의 독립적인 블록을 이용한 개발 방법을 이용한다.
말 그대로 한개의 페이지로 이루어진 어플리케이션을 의미한다. 기존 MPA(Multi Page Application)과 반대되는 개념이다.
기존에는 페이지에 부분이 바뀔때마다 리렌더링 돼서 불편했는데, SPA 방식은 필요한 데이터만 받아와서 수정해주기 때문에 화면에 계속 리렌더링 되는일이 없다.
리액트는 기존 자바스크립트 문법을 확장한 jsx문법으로 이루어져 있다. 한 페이지를 함수로 선언해주고 리턴문에다 html을 작성해서 DOM에 렌더링을 해준다. 직관적으로도 보기 편하고 변수를 설정해줄 수도 있고 다양하게 활용이 가능하다.
다만 리턴문을 쓸때는 꼭 한 개의 엘리먼트를 감싸줘야 한다. 즉 부모요소 하나가 반드시 있어야 한다.
리액트는 컴포넌트 단위로 페이지를 나누거나, 부분요소를 나눈다. 또한 props를 통해 부모로부터 자식에게 값을 넘겨줄 수 있다.
import { useState } from "react";
import "./App.css";
import AddButton from "./components/AddButton";
import User from "./components/User";
function App() {
const [users, setUsers] = useState([
{ id: 1, age: 30, name: "송중기" },
{ id: 2, age: 24, name: "송강" },
{ id: 3, age: 21, name: "김유정" },
{ id: 4, age: 29, name: "구교환" },
]);
const [name, setName] = useState("");
const [age, setAge] = useState("");
const nameChangeHandler = (event) => {
setName(event.target.value);
};
const ageChangeHandler = (event) => {
setAge(event.target.value);
};
// 추가 버튼
const clickAddButtonHandler = () => {
// 1. 새로운 형태의 객체를 만든다
// 2. 객체를 배열에 더한다
const newUser = {
id: users.length + 1,
age,
name,
};
setUsers([...users, newUser]);
alert("추가되었습니다!");
};
// 삭제 버튼
const clickRemoveButtonHandler = (id) => {
const delUser = users.filter((user) => user.id !== id);
setUsers(delUser);
alert("삭제되었습니다!");
};
return (
<>
<div className="App first">
<div>
<div className="input">
이름:
<input value={name} onChange={nameChangeHandler} />
나이:
<input value={age} onChange={ageChangeHandler} />
<AddButton addFunction={clickAddButtonHandler}>
추가
</AddButton>
</div>
{users.map((item) => {
return (
<User
key={item.id}
item={item}
removeFunction={clickRemoveButtonHandler}
/>
);
})}
</div>
</div>
</>
);
}
export default App;
위에 예시 코드를 보면 users에 데이터를 맵으로 뽑아내고 그안에 User라는 태그를 만들어 props를 통해 객체로 값을 넘겨줄 수 있다. 이때 왼쪽에 변수를 통해 전달하기 때문에 전달할 값은 객체안의 넣어주고 왼쪽에 item이나, removeFunction을 사용해야 한다.
const User = ({ item, removeFunction }) => {
return (
<div key={item.id} className="box">
{item.age} - {item.name}
<button className="del-btn" onClick={() => removeFunction(item.id)}>
닫기
</button>
</div>
);
};
export default User;
객체를 전달받을땐 지정한 변수를 써주면 된다. 필자는 처음에 저 변수랑 값 둘 중에 뭘 써야 되는지 너무 헷갈려서 왜 props를 넘겨줬는데 작동이 안되지?? 여러번 바보같이 같은 실수를 반복했다. ㅜㅜ
[부모] → [자식] 컴포넌트간 데이터 전달이 이루어지는 방법이 props인데, [부모] → [자식] → [그 자식] → [그 자식의 자식] 이 데이터를 받기 위해선 무려 3번이나 데이터를 전달해야한다. 이걸 바로 prop drilling, props가 아래로 뚫고 내려간다. 라고 한다.
이런 현상을 피하기 위해선 Redux와 같은 상태관리를 이용해 데이터를 관리해준다.
리액트에 훅이라고 하며 이 useState를 통해 변경할 값을 지정해주고 set으로 값을 변경해주며 리액트에도 화면에 렌더링 될 수 있도록 해준다. 리액트는 딱 한가지 useState를 통해서만 값을 변경할 수 있다는 것만 기억하면 된다.
모듈은 크게 두 종류로 나뉜다.
- 복수의 함수가 있는 라이브러리 형태의 모듈
- 개체 하나만 선언되어있는 모듈
파일에 개체가 하나만 있다는 표현으로 쓰는것이 export default 방식인데 대개 파일에는 개체가 하나만 존재하며, 이를 쓰면 export로만 넘겨주는 방식과 다르게 중괄호 { } 없이 모듈을 가져올 수 있다.