import "./App.css";
import DiaryEditor from "./DiaryEditor";
const App = () => {
return (
<div className="App">
<DiaryEditor />
</div>
);
};
export default App;
☑️ DiaryEditor : 일기장 컴포넌트
☑️ useState : 요소를 리액트가 직접 핸들링할 수 있도록 만들어야 함
☑️ 상태변화 함수 : input과 textarea가 받는 value prop으로 전달
useState("작성자"); : 초기값 설정
onChange
값이 실시간으로 바뀌도록 이벤트 설정(콜백함수 등록하여 event 객체인 e를 매개변수로 전달받게 됨)
사용자가 입력을 하면 어떤 사건이 발생했다고 인식하는데 onChange는 값이 바뀌었을 때 수행하는 이벤트
= input에 값이 바뀌었을 때 onChange의 Prop에 전달한 콜백함수를 수행한다라고 생각하면 됨
e.target.value
console을 통해 전달받은 이벤트 객체를 열어보면 target을 키를 열면 지금 바뀐 value 확인 가능
이벤트 객체의 target의 value를 이용하면 입력하고 있는 값을 콜백함수에 불러서 사용 가능
input이 변화해야 하는 값
setAuthor(e.target.value), setContent(e.target.value)
작성자 input이 변화해야 하는 값이 변화할 때마다 그 값으로 업데이트 시키면 state와 함께 input을 이용할 수 있게 됨
콜백함수가 수행될 때 매개변수인 이벤트 객체 e에서 지금 현재 입력받은(지금 현재 변화한) 값을 새로운 상태의 값으로 변화시키면서 author, content state가 바뀌어서 value가 바뀌고 실제로 화면에 렌더링된다.
const [author, setAuthor] = useState("");
const [content, setContent] = useState("");
<input name="author" value={author}
onChange={ (e) => {setAuthor(e.target.value);}
} />
<textarea name="content" value={content}
onChange={ (e) => {setContent(e.target.value);}
} />
☑️ 동일한 state (value, onChange의 콜백함수, 자료형(공백문자열)) 라면 하나의 state로 묶을 수 있다.
const [state, setState] = useState({
author: "",
content: "",
});
<input name="author" value={state.author}
onChange={ (e) => {
setState({
author: e.target.value,
content: state.content,
});
}
} />
<textarea name="content" value={state.content}
onChange={ (e) => {
setState({
content: e.target.value,
author: state.author,
});
}
} />
☑️ spread 연산자 활용
원래있던 state를 먼저 펼쳐주고 나서 변경하고자하는 state의 property를 마지막에 적어준다
const [state, setState] = useState({
author: "",
content: "",
});
<input name="author" value={state.author}
onChange={ (e) => {
setState({
...state,
author: e.target.value,
});
}
} />
<textarea name="content" value={state.content}
onChange={ (e) => {
setState({
...state,
content: e.target.value,
});
}
} />
☑️ 중복코드 제거 - eventHandler 합치기
const handleChangeState = (e) => {
setState({
...state,
[e.target.name]: e.target.value,
});
};
<input name="author" value={state.author} onChange={handleChangeState} />
<textarea name="content" value={state.content} onChange={handleChangeState} />
☑️ 감정점수 1~5점으로 표시 (select, option)
const [state, setState] = useState({
author: "",
content: "",
emotion: 1,
});
<select name="emotion" value={state.emotion} onChange={handleChangeState}>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
</select>
☑️ 저장하기 (button)
const handleSubmit = () => {
console.log(state);
alert("저장 성공!");
};
<button onClick={handleSubmit}>일기 저장하기</button>
☑️ CSS styling
.App {margin:0 auto;}
.DiaryEditor { border:1px solid #e5e5e5; text-align:center; padding: 20px; }
.DiaryEditor input, .DiaryEditor textarea { margin:0 0 20px 0; padding:10px; width:500px; }
.DiaryEditor textarea { width:500px; height:150px; }
.DiaryEditor select { margin:0 0 20px 0; padding:10px; width:500px; }
.DiaryEditor button { cursor:pointer; padding:10px; width:500px; }
📝 Result
import { useState } from "react";
const DiaryEditor = () => {
const [state, setState] = useState({
author: "",
content: "",
emotion: 1
});
const handleChangeState = (e) => {
setState({
...state,
[e.target.name]: e.target.value
});
};
const handleSubmit = () => {
console.log(state);
alert("저장 성공!");
};
return (
<div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
value={state.author}
onChange={handleChangeState}
name="author"
placeholder="작성자"
type="text"
/>
</div>
<div>
<textarea
value={state.content}
onChange={handleChangeState}
name="content"
placeholder="일기"
type="text"
/>
</div>
<div>
<span>오늘의 감정점수 : </span>
<select
name="emotion"
value={state.emotion}
onChange={handleChangeState}
>
<option value={1}>1</option>
<option value={2}>2</option>
<option value={3}>3</option>
<option value={4}>4</option>
<option value={5}>5</option>
</select>
</div>
<div>
<button onClick={handleSubmit}>일기 저장하기</button>
</div>
</div>
);
};
export default DiaryEditor;