터미널에서 내가 작업을 진행할 폴더로 이동한 뒤, yarn create react-app week_1
명령어를 통해 week_1이라는 폴더가 새로 생서되고 그 안에 react-app이 설치된다. 보일러 플레이트인 react-app을 이용해서 패키지가 다 깔려있는 상태로 시작하는 것이다.
week_1 폴더 안에서 jsconfig.json
파일을 하나 만들어서 아래와 같이 작성해서 넣어주면 앞으로 src 폴더 안의 파일들을 import 할 때는 상대경로를 작성해주지 않아도 된다.
// jsconfig.json
{
"compilerOptions": { "baseUrl": "src" },
"include": ["src"]
}
useState와 같은 hook을 사용하는 가장 근본적인 이유는 무엇일까? 그것은 바로 화면을 렌더링하기 위해서이다.
useState를 사용할 때는 초기값을 설정해주고, 배열을 반환 받는다. 첫 번째 반환받는 인자로 상태에 대한 데이터를, 두 번째 인자로 그 데이터를 바꿔주는 modifier 함수를 준다. 이때 데이터는 초기값으로 설정해준 값을 받는다.
useState를 사용해서 유저의 Id,pw를 입력받고 받은 값을 alert로 띄워서 보여주는 예시를 만들어보겠다.
// App.py
function App() {
const [data, setData] = useState({ id: "", pw: "" });
const handleChangeState = (e) => {
setData({ ...data, [e.target.name]: e.target.value });
};
const handleLogin = () => {
alert(`입력한 아이디 : ${data.id} 입력한 비밀번호 : ${data.pw}`);
setData({ id: "", pw: "" });
};
return (
<div>
<div>
아이디
<input name="id" type="text" value={data.id} onChange={handleChangeState} />
비밀번호
<input name="pw" type="text" value={data.pw} onChange={handleChangeState} />
</div>
<button onClick={handleLogin}>로그인하기</button>
</div>
);
}
function App() {
const [count, setCount] = useState(0);
const handleIncrease = () => {
setCount((count) => count + 1);
};
const handleDecrease = () => {
setCount((count) => count - 1);
};
return (
<div>
<h1>{count}</h1>
<button onClick={handleIncrease}>+</button>
<button onClick={handleDecrease}>-</button>
</div>
);
}
useState를 활용하여 Create, Read, Delete 기능을 구현해보겠다. (연습용이라 일부러 하나의 App.js 파일에 만들어서 가독성이 떨어짐)
import React, { useState, useRef } from "react";
import "App.css";
const UserItem = ({ userItem, onRemove }) => {
const handleRemove = () => {
window.confirm(`${userItem.id}번째 정보를 진짜 삭제하시겠습니까?`) && onRemove(userItem.id);
};
return (
<div>
<div className="UserItem">
<p>{`${userItem.name}`}</p>
<p>{`${userItem.age}`}</p>
</div>
<button onClick={handleRemove}>삭제하기</button>
</div>
);
};
const UserList = ({ userList, onRemove }) => {
// App의 전체 유저 정보가 담긴 데이터를 가지고 리스트를 만들어줌
// userList = [{name:"", age:""}, {정보2}..]
return (
<div className="UserList">
{/* userList의 길이만큼 userItem을 만들어야 하니까 map으로 생성 */}
{userList.map((i) => {
return <UserItem userItem={i} onRemove={onRemove} key={i.id} />;
})}
</div>
);
};
const UserEditor = ({ onCreate }) => {
const [users, setUsers] = useState({ name: "", age: "" });
// 이름과 나이를 입력했을 때
const handleChangeState = (e) => {
setUsers({ ...users, [e.target.name]: e.target.value });
};
// 추가하기 버튼을 눌렀을 때
const handleSubmit = () => {
onCreate(users);
setUsers({ name: "", age: "" });
alert("추가 완료!");
};
return (
<div>
<div>
<input name="name" type="text" value={users.name} onChange={handleChangeState} />
<input name="age" type="text" value={users.age} onChange={handleChangeState} />
</div>
<button onClick={handleSubmit}>추가하기</button>
</div>
);
};
function App() {
const [data, setData] = useState([]);
// 유저 key 생성
const dataId = useRef(0);
// 유저 생성
const onCreate = ({ name, age }) => {
// UserEditor에서 유저의 이름과 나이를 받으면 그 값으로 App의 data에 추가해주기
const newData = {
name,
age,
id: dataId.current,
};
dataId.current++;
setData([...data, newData]);
};
// 유저 삭제
const onRemove = (id) => {
const newUsers = data.filter((i) => i.id !== id);
setData(newUsers);
};
return (
<div>
<UserEditor onCreate={onCreate} />
<UserList userList={data} onRemove={onRemove} />
</div>
);
}
export default App;
아직은 컴포넌트를 어느 단계에서 분리해야하는지 정확하게 모르겠지만, 일단 기능 별로 구분해서 컴포넌트를 만들고 prop을 이곳저곳에서 사용하는 시행착오를 해보고 CRD 하는 것을 만들어보니 조금은 알겠다
역시 만들어보면서 좀 더 배워야겠다.