WEB/REACT

[React] ๋Œ“๊ธ€๊ธฐ๋Šฅ ๊ตฌํ˜„

mingzoo 2021. 1. 25. 16:01

๐Ÿ“–์š”์ฆ˜ ๋ฆฌ์•กํŠธ๋ฅผ ์–ด๋Š์ •๋„ ๊ณต๋ถ€ํ•˜๋ฉด์„œ ๋‚ด ํž˜์œผ๋กœ ๊ฐ„๋‹จํ•œ ๊ฒฐ๊ณผ๋ฌผ์„ ๋งŒ๋“ค์–ด๋ณด๊ณ  ์‹ถ๋‹ค๋Š” ์ƒ๊ฐ์— ๋ธ”๋กœ๊ทธ? 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;
728x90