REACT

DAY 76 - React HOMEWORK (2024.10.24)

summ.n 2024. 10. 24. 18:22

HOMEWORK

                      Todos

TodoForm                             TodoList           

상태변수 : text                                              TodoItem

포커스                                                            삭제 버튼 : onDelete

추가버튼 :  submit

seq를 잡아서 같은 공부하기가 두 개 들어간 상태에서 하나 지우면 하나만 지워지게 해야한다.

 


css

TodoForm.module.css

.TodoForm {
    text-align: center; 
    padding: 40px 0; 
    background: beige;
}
.TodoForm input {
    width: 300px; 
    height: 35px; 
    padding: 0 20px; 
    box-sizing: border-box; 
    vertical-align: top; 
    border: 1px solid #dcdcdc;
}
.TodoForm button {
    width: 80px; 
    height: 35px; 
    border: none;
}

TodoList.module.css

.TodoList {}
.TodoList li {
    padding: 15px 30px; 
    border-bottom: 1px solid #dcdcdc; 
    background: tomato;
}
.TodoList li span {
    margin-right: 20px; 
    font-size: 16px; 
    color: #fff ; 
    cursor: pointer;
}
.TodoList li em {
    color: #fff; 
    cursor: pointer;
}
.TodoList li button {
    float: right; 
    width: 80px;
}

.TodoList li.on span {
    color: yellow;
}
.TodoList li.on em {
    color: yellow ; 
    text-decoration: line-through;
}

Todos.module.css

.Todos {
    width: 450px;
    margin: 10px auto;
}
.Todos h1 {
    text-align: center; 
    padding: 10px 0; 
    font-size: 20px;
}

Todos.jsx

import React from 'react';
import { useRef } from 'react';
import { useState } from 'react';
import TodoForm from './TodoForm';
import TodoList from './TodoList';

import myStyle from '../css/Todos.module.css';
const Todos = () => {
    const [text, setText] = useState('');
    const textRef = useRef();
    const seq = useRef(1);

    const [list, setList] = useState([]);

    const onInput = (e) => {
        const {value} = e.target;
        setText(value);
    }

    const onAdd = (e) => {
        e.preventDefault(); 

        if(!text) 
            return;

        setList([
            ...list,
            {
                id: seq.current++, 
                text: text,
            },
        ])

        setText('');

        textRef.current.focus();
    }

    const onDelete = (id) => {
        console.log(id);
        setList(list.filter(item => item.id !== id))
    };

    return (
        <div className={myStyle.Todos}>
            <h1>일정관리</h1>
            <TodoForm text={text} seq={seq} textRef={textRef} onInput={onInput} onAdd={onAdd}/>
            <TodoList list={list} seq={seq} onDelete={onDelete}/>
        </div>
    );
};

export default Todos;

TodoForm.jsx

import React from 'react';
import myStyle from '../css/TodoForm.module.css';

const TodoForm = ({text, textRef, onInput, onAdd}) => {
    return (
        <div className={myStyle.TodoForm}>
            <form onSubmit={ onAdd }>
                <input type='text' name='text' value={ text } onChange={ onInput } ref={textRef}/>
                <button type='submit'>추가</button>
            </form>
        </div>
    );
};

export default TodoForm;

TodoList.jsx

import React from 'react';
import TodoItem from './TodoItem';

import myStyle from '../css/TodoList.module.css';
const TodoList = ({list, seq, onDelete}) => {
    return (
        <div className={myStyle.TodoList}>
            <ul>
            {
                list.map(item => <TodoItem key={seq} item={item} onDelete={onDelete}/>)
            }  
            </ul>
        </div>
    );
};

export default TodoList;

TodoItem.jsx

import React from 'react';

const TodoItem = ({ item, onDelete }) => {
    return (
        <div>
            <li>
                {item.text}  
                <button onClick={() => onDelete(item.id)}>삭제</button> 
            </li> 
        </div>
    );
};

export default TodoItem;


강사님 답

상태변수와 상태변수를 바꾸는 함수는 같이 있는게 좋다 !!!!

모든 상태변수를 부모가 가지고 있을 필요는 없다.

Todos.jsx

import React from 'react';
import { useRef } from 'react';
import { useState } from 'react';
import TodoForm from './TodoForm';
import TodoList from './TodoList';

import myStyle from '../css/Todos.module.css';
import TodoItem from './TodoItem';
const Todos = () => {
    const [list, setList] = useState([]);

    const seq = useRef(1);

    const onAdd = (text) => {
        setList([
            ...list,
            {
                seq: seq.current++, 
                text: text,
            },
        ])
    }

    const onDel = (seq) => {
        console.log(seq);
        setList(list.filter(item => item.seq !== seq))
    };

    return (
        <div className={myStyle.Todos}>
            <h1>일정관리</h1>
            <TodoForm onAdd={ onAdd }/>
            <TodoList list={ list } onDel={ onDel }/>
        </div>
    );
};

export default Todos;

TodoForm.jsx

text는 여기서만 쓰므로 여기에 선언하면 된다 !!

import React, { useRef, useState } from 'react';
import myStyle from '../css/TodoForm.module.css';

const TodoForm = ({ onAdd }) => {   
    const [text, setText] = useState('');
    
    const textRef = useRef();

    const onInput = (e) => {
        const {value} = e.target;
        setText(value);
    }

    const onSubmit = (e) => {
        e.preventDefault(); 

        if(!text) 
            return;

        onAdd(text); //입력한 text를 list에 추가

        setText('');

        textRef.current.focus();
    }

    return (
        <div className={myStyle.TodoForm}>
            <form onSubmit={ onSubmit }>
                <input type='text' name='text' value={ text } onChange={ onInput } ref={textRef}
                            placeholder='해야할 일을 입력하세요.'/>
                <button type='submit'>추가</button>
            </form>
        </div>
    );
};

export default TodoForm;

import React from 'react';
import TodoItem from './TodoItem';

import myStyle from '../css/TodoList.module.css';
const TodoList = ({list, onDel}) => {
    return (
        <div className={myStyle.TodoList}>
            <ul>
            {
                list.map(item => <TodoItem key={item.seq} item={item} onDel={onDel}/>)
            }  
            </ul>
        </div>
    );
};

export default TodoList;

 

import React from 'react';

const TodoItem = ({ item, onDel }) => {
    const { seq, text } = item
    return (
        <div>
            <li>
                { text }  
                <button onClick={() => onDel(seq)}>삭제</button> 
            </li> 
        </div>
    );
};

export default TodoItem;

 

이런식으로 삭제되고 새로 만들어도

한 번 만들어진 seq는 또 만들어지지 않는다.

 

 

대신 새로고침하면 seq가 새롭게 랜더링돼서 1부터 다시 시작하는 문제가 있다.

const seq = useRef(list.length + 1);

그래서 이걸로 바꿨는데 이것도 좀 꼬여서 어차피 나중에 DB가서 하면 이건 상관없어지니

일단 넘어갔다~