[React] 연락처 만들기

Suvina·2024년 4월 17일

React

목록 보기
17/22
post-thumbnail

App

import {useReducer, useRef, useCallback} from "react";
import ContactEditor from "./components/ContactEditor";
import ContactList from "./components/ContactList";
import "./App.css";

const mockData = [
    {
        id: 0,
        name: "박아무개",
        content: "010-2345-2323",
    },
    {
        id: 1,
        name: "홍길동",
        content: "031-232-2323",
    },
];

function reducer (state, action){
    switch (action.type){
        case "CREATE":
            return[action.data, ...state];
        case "DELETE":
           return state.filter((contact)=>contact.id !== action.targetId);
        default:
            return state;
    }
}

function App() {
    const [contacts, dispatch] = useReducer(reducer, mockData);
    const idRef= useRef("3");

    const onCreate = useCallback((name, content) => {
        dispatch({
            type: "CREATE",
            data: {
                id: idRef.current++,
                name: name,
                content: content,
            }
        })
    }, []);

    const onDelete = useCallback((targetId) => {
      dispatch({
          type: "DELETE",
          targetId: targetId,
      })
    }, []);

    return (
      <div className="App">
        <h2>Contact List</h2>
        <section>
          <ContactEditor
              onCreate={onCreate}
          />
        </section>
        <section>
          <ContactList
              contacts={contacts}
              onCreate={onCreate}
              onDelete={onDelete}
          />
        </section>
      </div>
  );
}

export default App;

ContactEditor

import React, {useRef, useState, memo} from "react";
import "./ContactEditor.css";

const ContactEditor = ({ onCreate }) => {

    const [name, setName] = useState("");
    const [content, setContent] = useState("");

    const nameRef = useRef();
    const contentRef = useRef();

    const onSubmit = () => {
        if(name === ""){
            nameRef.current.focus();
            return;
        }
        if(content === ""){
            contentRef.current.focus();
            return;
        }
        onCreate(name, content)
    }

    const onChangeName = (e) => {
        setName(e.target.value);
    }

    const onChangeContent = (e) => {
        setContent(e.target.value);
    }

    const onKeyDown = (e) => {
        if (e.keyCode === 13) {
            onSubmit();
        }
    }

    return (
        <div className="ContactEditor">
            <div className="title">Add Contact</div>
            <div className="input_wrapper">
                <input className="name" placeholder="이름 ..."
                       ref={nameRef}
                       value={name}
                       onChange={onChangeName}
                />
                <input className="contact" placeholder="연락처(이메일) ..."
                       ref={contentRef}
                       value={content}
                       onChange={onChangeContent}
                       onKeyDown={onKeyDown}
                />
            </div>
            <button onClick={onSubmit}>Add</button>
        </div>
    );
}
export default memo(ContactEditor);

ContactItem

import React, {memo} from "react";
import "./ContactItem.css";

const  ContactItem = ({ id, name, content, onDelete }) => {
    const onClickDeleteButton = () =>{
        onDelete(id);
    }

  return (
    <div className="ContactItem">
      <div className="name">{name}</div>
      <div className="contact">{content}</div>
      <button onClick={onClickDeleteButton}>🗑️ Remove</button>
    </div>
  );
}

export default memo(ContactItem);

ContactList

import "./ContactList.css";
import ContactItem from "./ContactItem";

export default function ContactList({ contacts, onDelete }) {
  return (
    <div className="ContactList">
      <div className="title">Contact List</div>
        {contacts.map((contact, id)=> {
            return(
                <ContactItem
                    key={id}
                    {...contact}
                    onDelete={onDelete}
                />
            )
        })}
    </div>
  );
}

설명은 나중에..

profile
개인공부

0개의 댓글