[React] ๋๊ธ๊ธฐ๋ฅ ๊ตฌํ
๐์์ฆ ๋ฆฌ์กํธ๋ฅผ ์ด๋์ ๋ ๊ณต๋ถํ๋ฉด์ ๋ด ํ์ผ๋ก ๊ฐ๋จํ ๊ฒฐ๊ณผ๋ฌผ์ ๋ง๋ค์ด๋ณด๊ณ ์ถ๋ค๋ ์๊ฐ์ ๋ธ๋ก๊ทธ? SNS?์ ๊ฐ์ ํ์์ ๊ฒ์๋ฌผ๊ณผ ๋๊ธ๊ณผ ์ข์์๋ฅผ ๊ตฌํํ ์ ์๋ ํ์ด์ง๋ฅผ ๋ง๋ค๊ณ ์๋ค.
ํ๋์ ์ฑ๊ธํ์ด์ง๋ฅผ ๋ง๋๋ ๊ฒ๋ ์ด๋ ๊ฒ ๋ง์ ์ํ์ฐฉ์ค๊ฐ ํ์ํ ๊ฑธ ๊ฒช์ด๋ณด๋, ์์ง ๊ฐ ๊ธธ์ด ๋ง์ด ๋ฉ๋ค๋ ์๊ฐ์ด ๋ค์๋ค๐ฅ
์ด ๊ธ์ ์ด๋ฒ ํ์ด์ง๋ฅผ ๊ตฌํํ๋ฉด์ ๋ด๊ฐ ๊ฒช์๋ ์ค๋ฅ๋ค๊ณผ ์ด๋ฅผ ํด๊ฒฐํ ๋ฐฉ๋ฒ๊ณผ ์ ๊ทธ๋ ๊ฒ ์จ์ผ๋งํ๋์ง ๊ทธ ์ด์ ์ ๋ํด์ ์จ๋ณด๋ ค๊ณ ํ๋ค.
์ด๋ฒ์ ๊ฒช์ ์ค๋ฅ๋ inputํ๊ทธ๋ก ์ด๋ฆ๊ณผ ๋๊ธ์ ๋ด์ฉ์ ์ ๋ ฅ๋ฐ์ ๋๊ธ์ ๋์ฐ๋ ๊ธฐ๋ฅ์ ๊ตฌํํ๊ณ ์์๋๋ฐ, ์ ๋ ฅ๋ฐ์ ๋ด์ฉ๋ค์ด ๋จ์ง ์๊ณ ๋น ์นธ์ด ๋จ๋ ๊ฒ์ด์๋ค.
๋๊ธ์ ์ ๋ ฅ์ ๋ฐ๋ ์ฝ๋๊ฐ ์์ฑ๋์ด์๋ commentInput.js์ ์ฝ๋๋ ์๋์ ๊ฐ๋ค.
import React, { useCallback, useState } from 'react';
import { MdAdd } from 'react-icons/md';
import './CommentInput.css';
const CommentInput = ({ onInsert }) => {
const [value, setValue] = useState({
name: '',
content: ''
});
const onChange = useCallback(
(e) => {
setValue(e.target.value)
},
[value]
)
const onSubmit = useCallback(
e => {
onInsert(value.name, value.content);
setValue({
name: '',
content: ''
});
e.preventDefault();
},
[onInsert, value],
);
return (
<form className="CommentInsert" onSubmit={onSubmit}>
<input classNames="inputNames"
placeholder="์ด๋ฆ"
value={value.name}
onChange={onChange}
/>
<input placeholder="๋๊ธ"
value={value.content}
onChange={onChange}
/>
<button type="submit">
<MdAdd />
</button>
</form>
)
}
export default CommentInput;
์ด ์ฝ๋์ ๊ฒฐ๊ณผ๋ก๋ ์๋์ ๊ฐ์ ์ฌ์ง์ฒ๋ผ ๋์ค๊ฒ ๋์๋ค.
์์ ์ฌ์ง์ฒ๋ผ ์ด๋ฆ๊ณผ ๋๊ธ ๋ด์ฉ์ด ๋ ์ผํ๋๋ฐ, ์ ๋ ฅ์ ๋ฐ์ผ๋ฉด ์๋์ฒ๋ผ ์๋ฌด๊ฒ๋ ์์ฑ๋์ง ์์ ๋๊ธ์ฐฝ์ด ๋์จ๋ค๋ ๋ฒ๊ทธ๊ฐ ์์๋ค. ๊ณผ์ฐ ์ด๋ค ๊ณณ์ด ๋ฌธ์ ์์๊น?
์ฒ์์๋ ์ฝ๋๋ฅผ ์ ์ฒด์ ์ผ๋ก ์ดํด๋ณด๋ฉด, ์ ๋ ฅ๋ฐ๋ ๊ณณ์์ ์๋ฅผ name, content๋ก ์ธ์์ ๋ชปํ๋๊ฑฐ ์๋๊น? ๋ผ๋ ์๊ฐ์ ๊ทธ ๋ถ๋ถ์ ๋ค์ ์ดํด๋ณด์์๋ค. ๊ทธ๋์, ์ํฐ๋ฅผ ์น๋ฉด ๋ฐ์ดํฐ๊ฐ onSubmit๋ก ๊ฐ์ onInsert๋ก ๊ฐ๊ธฐ๋๋ฌธ์ ์ด ๋ ํจ์๋ฅผ ์ดํด๋ณด์์ง๋ง ๋ง๋ ํ ๋ฐฉ์์ ์ฐพ์ง ๋ชปํ์๋ค.
๊ทธ๋ฌ๋ค๊ฐ, ์ง์ธํํ ์ฝ๋์ ๋ฌธ์ ์ ์ ๋ด๋ฌ๋ผ๊ณ ๋ถํํ๊ณ onChange๋ถ๋ถ์ ๋ค์ ๋ณด๋ผ๋ ํผ๋๋ฐฑ์ ๋ฐ์๋ค.
์ผ๋จ ํฐ ๋ฌธ์ ๊ฐ ์์๋ค.
"onChange๋ฅผ ๋๊ฐ๋ก ๋๋ ์ผ๋๋ค๋ ๊ฒ"
=> onChangeํจ์๋ฅผ ํ๋๋ก ๋ฐ์ผ๋๊น value๊ฐ dictํ์์์ ๊ทธ๋ฅ ๋ฌธ์์ด ๋ณ์๋ก ๋ฐ๋๋ค๋ ์ด์ ์๋ค.
๋๋ name๊ณผ content๋ฅผ value๋ก ๋ฌถ์ด์ ์ฌ์ฉํ๊ธฐ๋๋ฌธ์ ๊ด์ฐฎ์ ๊ฑฐ๋ผ๊ณ ์๊ฐํ์ง๋ง, ์ค์ฐ์ด์๋ ๊ฒ์ด๋ค.
๋ฐ๋ผ์, ์๋์ ์ฝ๋์ฒ๋ผ onChange ํจ์๋ฅผ ๋ ๊ฐ๋ก ๋๋ด๋ค.
const onChangeName = useCallback(e => {
setValue(e.target.value.name);,
}, []);
const onChangeContent = useCallback(e => {
setValue(e.target.value.content);
}, []);
์ง๊ธ๋ณด๋ ๊ต์ฅํ ์ฐฝํผํ ์ฝ๋์ด์ง๋ง, ์ด๋ ๊ฒ ๊ณ ์ณค์๋ค. ์ด๋ ๊ฒ ๊ณ ์น๋ฉด ํด๊ฒฐ๋ ๊ฑฐ๋ผ๊ณ ๊ธฐ๋์ ๋ถํ์์๋๋ฐ...๋๋ฆ๋๋ก ๋๋ ์ ์์ฑํ๋ค๋ ์ฌ์ค์ ๋ฟ๋ฏํดํ๋ฉด์ ๋ค์ ์คํ์์ผ๋ดค์ง๋ง, ๋ ์ค๋ฅ์๋ค. ์!?!?!?!?๋ผ๋ ์๊ฐ์ ๋ ๋ฉ๋ถ์ ๋น ์ก์๋ค.
๋ญ๊ฐ ๋ฌธ์ ์์๊น
์ด๋ฒ์๋ ๋จผ์ ํด๊ฒฐ๋ฐฉ๋ฒ์ ์ ์ํด์ฃผ๊ณ ์ค๋ช ์ ํด์ผ๊ฒ ๋ค.
์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ๊ณ ์น๋ฉด ๋ฌธ์ ๊ฐ ํด๊ฒฐ๋๋ค.
const onChangeName = useCallback(
(e) => {
setValue({
name: e.target.value,
content: value.content,
});
},
[value]
);
const onChangeContent = useCallback(
(e) => {
setValue({
name: value.name,
content: e.target.value,
});
},
[value]
);
์ฌ๊ธฐ์ e.target.value์ ๋ํ ๊ณต๋ถ๊ฐ ํ์ํ๋ค๊ณ ๋๊ผ๋ค.
๊ฐ๋จํ ์์ฝํ์๋ฉด, e.target์ผ๋ก ๊ฐ์ฒด๋ฅผ ๋ถ๋ฌ์ค๋๊ฒ์ด๋ค. ๋ฐ๋ผ์, ์์ ์ฝ๋๋ฅผ ๋น๋ ค์ค์๋ฉด e.target.value์ด๋ฉด value์ ๊ฐ์ ๋ถ๋ฌ์์ฃผ๋ ๊ฒ์ด๋ค.
setValue({name: e.target.value})์ด๋ฉด dictํ์์ผ๋ก ๋ํ๋ธ ๊ฑธ๋ก "ํค๊ฐ : ๊ฐ"์ ๋ณด์ฌ์ฃผ๋ ๊ฒ์ด๋ค.
ํจ์๋ฅผ ๋๊ฐ๋ก ๋๋์๋ค๋ณด๋ ํจ์์ ๋ฐ๋ผ ๋ฐ๊พธ๋ ค๋ ๋ณ์๊ฐ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ํจ์์ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ๊ฐ ๋ค๋ฅด๊ฒ ํด์ฃผ๋ ๊ฒ์ด๋ค.
const onChangeName = useCallback(
(e) => {
setValue({
...value,
name: e.target.value,
});
},
[value]
);
const onChangeContent = useCallback(
(e) => {
setValue({
...value
content: e.target.value,
});
},
[value]
);
์ด๋ ๊ฒ ์ฝ๋๋ฅผ ๋ฐ๊ฟ์ค๋ ๋๊ฐ์ด ์๋๋๋ค.
๋๋ฌด ์กฐ๊ธํ๊ฒ ๋ค๊ฐ๊ฐ์ ๊ทธ๋ฐ์ง ์ด๋ ๊ฒ ํ๋์ ์์ ํ๋ก์ ํธ๋ฅผ ์ค์ค๋ก ํด๋ณด๋ ๊ฐ๋ ์ด ๋ง์ด ๋ถ์กฑํ๋ค๊ณ ์๊ฐ์ด ๋ค์๋ค.
๋ค์ ์ฐจ๊ทผํ ๊ณต๋ถํ๋ฉด์ ๊ฐ๋ ์ ํํํ ๋ค์ ธ์ผ๊ฒ ๋ค๋ ๊ฒฐ์ฌ์ ํ๋ค.
๋ค์๋ฒ์๋ ์ด ํ์ด์ง์ ์ข์์ ๊ธฐ๋ฅ์ ์ถ๊ฐํด์ ํฌ์คํธ๋ฅผ ๋ค๊ณ ์์ผ๊ฒ ๋ค๐
[์ ์ฒด์ฝ๋] - input์ฐฝ ๊ด๋ จ ์ฝ๋๋ง
์์ ์ ์ฒด์ฝ๋๋ ์ด ํ์ด์ง์ ๋ชจ๋ ๊ธฐ๋ฅ์ด ๊ตฌํ๋๊ณ ์ฌ๋ฆฌ๊ฒ ์ต๋๋น
App.js
import React, { useState, useRef, useCallback } from 'react';
import './App.css';
import Template from './Template';
import CommentInput from './commentInput';
import Comment from './Comment';
import Article from './Article';
function App() {
const [comments, setComments] = useState([
{ id: 1, name: 'Minjoo Park', content: 'I like it!', }
]);
const nextId = useRef(1);
const onInsert = useCallback(
(name, content) => {
const comment = {
id: nextId.current,
name,
content
};
console.log(name);
console.log(content);
setComments(comments => comments.concat(comment));
nextId.current += 1; //nextId 1์ฉ ๋ํ๊ธฐ
},
[comments],
);
return (
<div>
<Template>
<Article />
<CommentInput onInsert={onInsert} />
</Template>
<div style={{ marginBottom: "4rem" }}>
{comments.map((comment) => {
return (
<Comment
key={comment.id}
id={comment.id}
name={comment.name}
content={comment.content}
/>
)
})}
</div>
</div>
);
}
export default App;
commentInput.js
import React, { useCallback, useState } from 'react';
import { MdAdd } from 'react-icons/md';
import './CommentInput.css';
const CommentInput = ({ onInsert }) => {
const [value, setValue] = useState({
name: '',
content: ''
});
const onChangeName = useCallback(
(e) => {
setValue({
name: e.target.value,
content: value.content,
});
},
[value]
);
const onChangeContent = useCallback(
(e) => {
setValue({
name: value.name,
content: e.target.value,
});
},
[value]
);
const onSubmit = useCallback(
e => {
onInsert(value.name, value.content);
setValue({
name: '',
content: ''
});
e.preventDefault();
},
[onInsert, value],
);
return (
<form className="CommentInsert" onSubmit={onSubmit}>
<input classNames="inputNames"
placeholder="์ด๋ฆ"
value={value.name}
onChange={onChangeName}
/>
<input placeholder="๋๊ธ"
value={value.content}
onChange={onChangeContent}
/>
<button type="submit">
<MdAdd />
</button>
</form>
)
}
export default CommentInput;