
React에서 상태(State)를 관리하기 위해 사용하는 Hook 중 하나인 useState() 는 함수형 컴포넌트에서 상태를 추가하고 변경할 수 있도록 하는 역할을 합니다.
useReact()를 사용하기 위해서는 react를 import해줘야합니다. 그리고 다음과 같이 함수형태로 선언을 해주시면 됩니다.
content가 변수가 되며, setContent가 setter가 됩니다.
import { useState } from "react";
const DiaryEditor = () => {
const [content, setContent] = useState("");
return (생략...)
}
export default DiaryEditor;
useState와 관계 없는 번외지만, DiaryEditor라는 함수가 곧 js파일명과 같게 됩니다. 이를 export하여 최종적으로 렌더링을 관장하는 App.js에 사용할 수 있게 됩니다.
위에 코드를 실행해보면 아무런 입력도 되지 않으실겁니다.
React에 값을 변화시켜주기 위해서는 useState의 두번째 인자를 선언하여 setter가능 합니다.
import { useState } from "react";
const DiaryEditor = () => {
const [author, setAuthor] = useState("디폴트");
const [content, setContent] = useState("디폴트");
return <div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
name="author"
type="text"
value={author}
placeholder="직성자"
// onChange는 C가 대문자입니다. react의 component를 사용하는 겁니다.
onChange = {(e) => {
console.log(e.target.value);
setAuthor(e.target.value);
// 다음과 같이 event에서 현재 타겟의 입력값을 가져와
//author변수에 넣어주게 됩니다.
}}
/>
</div>
<div>
<textarea
name="content"
type="text"
value={content}
placeholder="일기"
onChange = {(e) => {
console.log(e.target.value);
setContent(e.target.value);
}}
/>
</div>
</div>
}
export default DiaryEditor;
다음의 코드는 사실 같은 기능을 하는 함수들입이니다 그냥 값과 setter로 구성되어있죠.
const [author, setAuthor] = useState("디폴트");
const [content, setContent] = useState("디폴트");
해당 useState는 다음과 같이 표현 가능합니다.
const [state, setState] = useState({
author: "",
content: "",
})
마찬가지로 onCange함수, value도 다음과 같이 표현이 가능해집니다.
value={state.author} // 이것도 변경해야합니다.
onChange = {(e) => {
console.log(e.target.value);
//setAuthor(e.target.value); //1
setState({ //2
author: e.target.value,
content: state.content,
})
해당함수는 spread 표현식으로 다음과 같이 최적화가능합니다.
onChange = {(e) => {
console.log(e.target.value);
// setState({ //2
// author: e.target.value,
// content: state.content,
// })
setState({ //3
...state,
author: e.target.value,
})
}}
당연하겠지만 onChange를 공통으로 사용가능하게 Handler를 하나 제작해줍시다.
setState() 를 function 묶어 사용하시고 (Arrow function으로 해도 됩니다.)
괄호표기법으로 target을 event 단위로 셋팅하게 맞춰주시면 됩니다.
function ChangeHandler(e) {
setState({
...state,
[e.target.name]: e.target.value,
});
}
이렇게 되면 target이 되는 input tag에 naming을 해줘야 겠죠? 우리는 위에서 이미 작성을 해왔기 때문에 별다른 수정은 필요없습니다.
<input name="author'/>
<textarea name="content"/>
그리고 JSX의 onChange부분에서 함수실행을 하면 됩니다.
<input
name="author"
type="text"
value={state.author}
onChange={ChangeHandler} // 요기 수정
placeholder="직성자"/>
리액트에서는 DOM 노드나 React 엘리먼트에 접근하기 위한 방법으로 Ref라는 API를 제공합니다.
다음과 같이 useRef()를 선언해주시고 어떤 엘리먼트에 접근할건지 해당 노드에 선언해주시면 됩니다. 마찬가지로 react 줄에 import해줍니다.
const authorInput = useRef();
const contentInput = useRef();
// 중략...
<input
ref={authorInput}
name="author"
type="text"
value={state.author}
onChange={ChangeHandler}
placeholder="직성자"/>
이제 우리는 author엘리먼트에 접근할 수 있는 방법이 생겼습니다. input에 입력이 없으면 focus를 발생하는 간단한 script를 작성해봅니다.
const SubmitHandler = () => {
if(state.author.length < 1) {
authorInput.current.focus();
return;
}
if(state.content.length < 1) {
contentInput.current.focus();
return;
}
console.log(state);
alert("save complete!");
setState({
author: "",
content: ""
}) // 저장하고 초기화하기위한...
};
emotion을 추가하여 만들었습니다. App.js에도 <DiaryEditor />추가해주시면 됩니다.
import {useRef, useState} from "react";
const DiaryEditor = ({onCreate}) => {
const authorInput = useRef();
const contentInput = useRef();
const [state, setState] = useState({
author: "",
content: "",
emotion: 1,
})
//const [author, setAuthor] = useState("디폴트");
//const [content, setContent] = useState("디폴트");
function ChangeHandler(e) {
setState({
...state,
[e.target.name]: e.target.value,
});
}
const SubmitHandler = () => {
if(state.author.length < 1) {
authorInput.current.focus();
return;
}
if(state.content.length < 1) {
contentInput.current.focus();
return;
}
onCreate(state.author, state.content, state.emotion);
console.log(state);
alert("save complete!");
setState({
author: "",
content: "",
emotion: 1
})
};
return <div className="DiaryEditor">
<h2>오늘의 일기</h2>
<div>
<input
ref={authorInput}
name="author"
type="text"
value={state.author}
onChange={ChangeHandler}
placeholder="직성자"
/>
</div>
<div>
<textarea
ref={contentInput}
name="content"
type="text"
value={state.content}
onChange={ChangeHandler}
placeholder="일기"
/>
</div>
<div>
<span>오늘의 감정점수 : </span>
<select name="emotion"
value={state.emotion}
onChange={ChangeHandler}>
<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>
<button onClick={SubmitHandler}>save</button>
</div>;
};
export default DiaryEditor;