Hell路 World 삐약-
[React] 리액트 기초. 할 일 목록 To do List 만들기 본문
Reactjs

[React] 리액트 기초. 할 일 목록 To do List 만들기

날으는쏘피 2021. 8. 17.
728x90

리액트가 공개(2013년)되고 개발자들이 막 사용하기 시작했을때는 이정도 수준의 프로젝트도 취업준비할때 포트폴리오로 제출가능했던 때가 있다고 한다.

아... 리액트... 일찍 배웠어야 했어......

 

anyway.

지난 시간에는 리액트 기초 내용 총집합이라고 할 수 있는 To do List만들기를 했다.

완성된 모습은 아래 gif와 같다.

아니 저거 체크하면 hotpink로 해놨는데 gif로 만드니까 왜저뤠.................ㅋㅋㅋㅋㅋㅋㅋ

 

리액트 정리 포스팅이므로 css는 생략한다.

 

 

프로젝트 구조는 아래와같다

 

 

일단 App.js에 메인 컴포넌트가 될 Todo.js를 import 한다

 

 

지난 스타벅스 복습 포스팅은 작업하는 순서대로 썼는데 그렇게 하니까 복습하는 시간보다 포스팅 하는 시간이 더 길어지는... 배보다 배꼽이 되는 상황이 되어 일단 전체 복습겸 재구현을 해보고 완성된 소스를 보고 한꺼번에 정리하려고 한다.

 

반응형
  • Todo.js

 

Todo.js

 

useRef는 리액트 수업 셋째날 배워서 잊어버릴때 즈음 form을 사용하는 예재마다 요긴하게 사용하는 것 같다.

사용자로부터 입력받은 데이터에 고유한 id값을 설정할때 사용하거나 DOM의 특정 input에 .focus() 를 적용할때 사용한다.

 

여기서도 8번 줄에 보면 id로 사용할 변수 no를 useRef로 만들었다.

이렇게 설정된 값은 해당 프로젝트가 돌아가는 lifecycle동안은 고유하게 유지가되기때문에 id로 사용하기 딱이다.

 

 

useRef
1. DOM에 접근(이렇게 쓸 경우의 수가 많지않다)
2. 어떤 가변값을 유지하는데에 편리함

- DOM을 직접 선택해야하는 상황
- 특정요소의 값을 가져오기
- 스크롤바 위치
- 포커스 설정

const 사용자정의이름 = useRef(null)
const 사용자정의이름 = useRef()
const 사용자정의이름 = useRef(숫자)

<실제돔 ref={사용자 정의이름}>

사용자정의이름.current
사용자정의이름.current.xxx명령어
.current 프로퍼티에 변경 가능한 값을 담고 있는 "상자"

 

 

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


const Todo = () => {
    const no = useRef(1) //할 일(item)의 고유 id가 될 숫자
    const [todo, setTodo] = useState([]) 

	//고유 id값을 받아 해당 item삭제(해당 item을 제외한 값만 필터링)
    const onDel = (id)=>{
        setTodo(todo.filter(todo => todo.id !== id))
    }
	
    //고유 id값을 받아 해당 item의 체크 상태를 설정
    const onToggle= (id)=>{
        setTodo(todo.map(item=> item.id ===id? {...item, check : !item.check } : item))
    }

	//form에 입력받은 값을 새로운 doto item으로 추가
    const onAdd = (text)=>{
        setTodo([
            ...todo,
            {
                id : no.current++,
                text,
                check: false
            }
        ])    
    }
    
    
	//TodoForm컴포넌트에는 onAdd함수만 넘겨주고 List에는 todo객체와 토글,삭제 함수를 넘겨준다
    return (
        <div className="Todos">
            <h1>Things to do</h1>
            <TodoForm onAdd={onAdd}/>
            <TodoList todo={todo} onToggle={onToggle} onDel={onDel}/>  
        </div>
    );
};

export default Todo;

 

 

처음에 할 일을 완료 후 체크를 설정하는걸 어떻게 적용하는지 고민했는데

리스트를 통째로 가져와서 해당 id값의 아이템 check값만 기존의 check값의 반대(!item.check)로 설정해주면 된다

중요한건 스프래드연산자(...)로 기존의 값을 그대로 받아오고 check값만 변경한다는 것. 

 

이게 코드를 보니까 알겠는데 아직 생각으로만 퍼뜩 떠오르질 않는걸 보니 리액트 아직 멀었네...ㅠ

 

 

onAdd메소드에서도 스프레드 연산자로 기존의 데이터들을 가져오고 추가로 입력한 값은 받아서 새로운 데이터 넣어준다.

id는 위에서 썼던 것 처럼 no값을 받아오는데 사용자가 데이터를 입력할때마다 1씩 커져야하므로 현재의 값을 반환하는 .current에 ++ 해준다. 

check는 false를 default로 설정.

 

 

 

  • TodoForm.js

 

TodoForm.js

 

버튼을 눌렀을때 뿐만아니라 사용자가 input 폼에 값을 입력하고 enter를 쳐도 추가가 되도록 만드려면 formsubmit을 사용해야 한다. 

 

사용자로부터 입력받은 값이 변할때마다 바로바로 캐치해주는 onChange함수를 설정한다.

이번 예제에는 input값이 하나밖에 없기때문에 간단하게 비구조할당은 간단하게 {value}만 받는다.

 

 

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

const TodoForm = ({onAdd}) => {
    const textRef = useRef('') //입력후 input에 focus()해주기 위해 설정
    const [text, setText] = useState('') // 사용자로부터 받은 입력값 상태
    
    const changeInput = (e)=>{
        const {value} = e.target
        setText(value)
    }

    const onSubmit=(e) =>{
        e.preventDefault() //submit후에 새로고침을 방지하기 위해 꼭 필요하다

        if(!text) return //입력값이 없으면 실행되지 않는다
        onAdd(text)
        setText('') //input란을 다시 공란으로 만든다
        textRef.current.focus() //input란에 포커스
    }
    
    return (
        <form className="TodoForm" onSubmit={onSubmit}>
        <input type="text" value={text} onChange={changeInput} ref={textRef}/>
        <button type="submit">Add</button>
        </form>

    );
};

export default TodoForm;

 

728x90

 

  • TodoList.js

 

TodoList.js

 

 

메인컴포넌트에서 받아온 데이터와 onToggle, onDel함수를 map으로 TodoItem.js에 넘겨준다

 

 

import TodoItem from './TodoItem';
import '../css/TodoList.css'

const TodoList = ({todo, onToggle, onDel})=> {
    
    return (
        <ul className="TodoList">
            {
                todo.map(item => <TodoItem key={item.id} item={item} onToggle={onToggle} onDel={onDel}/>)
        }
        </ul>
    );
    
}

export default TodoList;

 

 

  • TodoItem.js

 

TodoItem.js

 

 

실질적으로 데이터에 변화를 주게되는 onToggle과 onDel 함수를 사용하는 TodoITem컴포넌트.

각 함수를 실행할때 id값을 매개변수로 받는데 이때 반드시 화살표 함수로 묶어줘야한다.(그렇지 않으면 페이지가 실행될때 바로 함수가 실행되어버린다)

 

check 유무 설정은 check값이 true인지 false인지에 따라 삼항연산자를 사용해 간단하게 true일 경우 클래스명에 on을 주어서 처리했다.

 

import React from 'react';

const TodoItem = ({item, onToggle, onDel}) => {
    const {id, text, check} = item

    return (
        <li className={check ?`on` : ""}>
            <span  onClick={()=>onToggle(id)} >&#10003;</span>
            <em>{text}</em>
            <button onClick={()=>onDel(id)}>&#10799;</button>
        </li>
    );
};

export default TodoItem;

 

 

 

크... 광복절 휴일이라 지난주에 수업이 없었는데 복습 안했으면 큰일날뻔....

이번주 수업가기 전에 지난시간에 배운 친구목록이랑 영화목록도 복습해서 정리해야겠다

 

728x90
Comments