[React] to-do list

2022. 6. 22. 15:49·Stack/React

App.js

import './App.css';
import { useState, useRef } from 'react';
import CreateTodo from './components/CreateTodo';
import TodoList from './components/TodoList';

function App() {
    const [ inputs, setInputs ] = useState({
      todo:"",
    });
    const onChange = (e) => {
      const { name, value } = e.target;
      setInputs({
        ...inputs,
        [name]:value
      })
      console.log(inputs);
    }
    const { todo } = inputs;
    const [ todos, setTodos] = useState([

    ])
    const nextId = useRef(1);
    const onCreate= () => {
    const todolist = {
      id:nextId.current,
      todo,
    }

    setTodos([...todos, todolist]);
    setInputs({
      todo:"",
    })
    nextId.current +=1; 
  }
  const onDelete = (id) => {
    setTodos(todos.filter(todolist=> id !== todolist.id));
  }
  const onToggle = (id) => {
    setTodos(todos.map(todolist=> id === todolist.id ? {...todolist, active: !todolist.active} : todolist ));
  }
  return (
    <div className="App">
        <CreateTodo todo={todo} onChange={onChange} onCreate={onCreate} />
        <TodoList todos={todos} onDelete={onDelete} onToggle={onToggle}/>
    </div>
  );
}


export default App;

 

CreateTodo.js

import React from 'react';
import './TodoList.css'
const CreateTodo= ({todo, onChange, onCreate}) => {
    return (
        <div>
            <header>
                <h1>to do list</h1>
                <div id='todo_box'>
                    <input name="todo" value = {todo} onChange={onChange}/>
                    <button onClick={onCreate}>+</button>
                </div>
            </header>
        </div>
    );
};

export default CreateTodo;

 

TodoList.js

import React from 'react';
import './TodoList.css'
const Todo = ({todo, onDelete, onToggle}) => {
    return (
        <div id= "todo">
            <span id="todotodo" className={todo.active ? 'active': ""} onClick={()=>{onToggle(todo.id) }}>{todo.todo}</span>
            <button id="delBtn" onClick={()=>{
                onDelete(todo.id);
            }}>X</button>
        </div>
    )
}

const TodoList = ({todos, onDelete, onToggle}) => {
    return (
        <div class="lists">
            {todos.map(todo =><Todo todo={todo} key={todo.id} onDelete={onDelete} onToggle={onToggle}/> )}
        </div>
    );
};



export default TodoList;

 

TodoList.css

*{padding: 0; margin: 0 auto; box-sizing: border-box;}
header {
    background-image: linear-gradient(135deg, #d2f985 0%, #fdd2c8 100%);
    width: 900px;
    height: 140px;
}
h1 {
    padding-top: 25px;
    padding-bottom: 8px;
    color: #222;
}
#todo_box {
    display: flex;
    align-items: center;
}
input {
    width: 600px;
    height: 28px;
    padding-left: 10px;
    border-radius: 25px;
    outline: none;
    border: none;
    margin-right: -120px;
}
.lists {
    width: 900px;
    background-color: #eee;
    padding: 8px 0;
    padding-left: 90px;
    text-align: left;
    line-height: 2.5;
}
button {
    padding: 0px 8px;
    border-radius: 25px;
    border: none;
    outline: none;
    background-color: #fff;
    font-size: 24px;
    cursor: pointer;
}
#todo {
    display: flex;
}
#todotodo {
    margin-left: 0px;
    cursor: pointer;
}
#delBtn {
    font-size: 16px;
    background-color: transparent;
    margin-right: 80px;
}
.active {
    text-decoration: line-through;
}

 


 

쌤 코드

App.js

import './App.css';
import { useState, useRef } from 'react'   // id를 계속 증가시키기위해 useRef 사용
import TodoLists from './components/TodoLists';
import CreateTodo from './components/CreateTodo';

function App() {
  const name = "abc";
  const [ list, setList ] = useState("");
  // input의 값을 입력할 때 (input의 value가 변경될 때)
  // onChange 함수를 실행
  // state인 list값을 input의 value 값으로 업데이트
  const onChange = (e)=> {
    const { value } = e.target;
    // console.log(e.target)
    setList(value);
  }
  // CreateTodo 컴포넌트에서 + 버튼을 클릭하면
  // todos배열에 할 일 객체가 추가됨
  const onCreate = () => {
    const listobj = {
      id: nextId.current,
      list: list,
      isDone: false,
    }
    setTodos([...todos, listobj]);  // 원래 배열(todos)을 펼쳐서 새로운 애(listobj)를 추가하기
    nextId.current +=1;
    setList("");
  }
  const [ todos, setTodos ] = useState([
    {
        id:1,
        list: "해야할일1",
        isDone: false,
    },
    {
        id:2,
        list: "해야할일2",
        isDone: false,
    },
    {
        id:3,
        list: "해야할일3",
        isDone: false,
    }
])
const nextId = useRef(todos.length+1);

// 항목삭제
// 삭제 클릭시 id값을 인수로 받아서
// todos배열에서 id값이 다른 객체만 업데이트
const onDelete = (id)=> {
  setTodos(todos.filter(todo=>id !== todo.id));
}
  return (
    <div className="App">
      <CreateTodo list={list} onChange={onChange} onCreate={onCreate}/>
      <TodoLists todos={todos} name={name} onDelete={onDelete}/>
    </div>
  );
}

export default App;

 

CreateTodo.js

import React from 'react';
import './TodoList.css'

const CreateTodo = ({onChange, list, onCreate}) => {
    return (
        <div>
            <header>
                <h2>to do list</h2>
                <div id='todo_box'>
                    <input type="text" value={list} name="newlist" onChange={onChange}/>
                    {/* (e)=>onChange(e.target.value) */}
                    <button onClick={onCreate}>+</button>
                </div>
            </header>
        </div>
    );
};

export default CreateTodo;

 

TodoList.js

import React from 'react';

//rsc
const TodoList = ({todo, onDelete}) => {
    return (
        <div id="todo">
             <span id="todotodo">{todo.list}</span>
             <button id="delBtn" onClick={()=>{onDelete(todo.id)}}>X</button>
        </div>
    );
};

export default TodoList;

 

TodoLists.js

import React from 'react';
import TodoList from './TodoList';
import './TodoList.css'

const TodoLists = ({todos, onDelete}) => {
    return (
        <div class="lists">
            {todos.map(todo=><TodoList todo={todo} key={todo.id} onDelete={onDelete}/>)} 
        </div>
    );
};

export default TodoLists;

 

 

 

Reducer 버전

AppReducer.js

import './App.css';
import { useRef, useReducer } from 'react'; 
import CreateTodo from './components/CreateTodo';
import TodoLists from './components/TodoLists';

const initialState = {
    text: "",
    todos: [
        {
            id:1,
            todotext: "리액트 공부하기",
            isDone: false,
        },
        {
            id:2,
            todotext: "타입스크립트 공부하기",
            isDone: false,
        },
        {
            id:3,
            todotext: "reducer 공부하기",
            isDone: false,
        }
  ]
}
function reducer(state, action) {
  switch(action.type) {
    case "CHANGE_INPUT":
      return {
        ...state,
        text :action.text
      };
      case "CREATE_TODO":
      return {
        text: "",
        todos: state.todos.concat(action.todo)
      }
      case "DELETE_TODO":
        return {
          ...state,
          todos: state.todos.filter(todo=> todo.id !== action.id)
        };
        case "ISDONE_TODO":
        return {
          ...state,
          todos: state.todos.map(todo => 
            todo.id === action.id ? {...todo, isDone: !todo.isDone}: todo)
        }
      default:
      return state;
  }
}
function App() {
  const [state, dispatch] = useReducer(reducer, initialState)
  const { text, todos } = state;
  const onChange = (e) => {
    dispatch({
      type: "CHANGE_INPUT",
      text: e.target.value
    })
    console.log(e.target.value)
  }
  const nextId = useRef(4);
  const onCreate = () => {
       dispatch({
      type: "CREATE_TODO",
      todo: {
        id: nextId.current,
        todotext: text,
        isDone: false,
      }
    })
  }
  const onDelete = (id) => {
    dispatch({
      type: "DELETE_TODO",
      id: id,
    })
  }
  const onToggle = (id) => {
    dispatch({
      type: "ISDONE_TODO",
      id: id
    })
  }
  return (
      <div className="App">
        <CreateTodo text = {text} onChange={onChange} onCreate={onCreate}/>
        <TodoLists todos={todos} onDelete={onDelete} onToggle={onToggle}/>
      </div>
    );
} 

export default App;

 

CreateTodo.js

import './App.css';
import { useRef, useReducer } from 'react'; 
import CreateTodo from './components/CreateTodo';
import TodoLists from './components/TodoLists';

const initialState = {
    text: "",
    todos: [
        {
            id:1,
            todotext: "리액트 공부하기",
            isDone: false,
        },
        {
            id:2,
            todotext: "타입스크립트 공부하기",
            isDone: false,
        },
        {
            id:3,
            todotext: "reducer 공부하기",
            isDone: false,
        }
  ]
}
function reducer(state, action) {
  switch(action.type) {
    case "CHANGE_INPUT":
      return {
        ...state,
        text :action.text
      };
      case "CREATE_TODO":
      return {
        text: "",
        todos: state.todos.concat(action.todo)
      }
      case "DELETE_TODO":
        return {
          ...state,
          todos: state.todos.filter(todo=> todo.id !== action.id)
        };
        case "ISDONE_TODO":
        return {
          ...state,
          todos: state.todos.map(todo => 
            todo.id === action.id ? {...todo, isDone: !todo.isDone}: todo)
        }
      default:
      return state;
  }
}
function App() {
  const [state, dispatch] = useReducer(reducer, initialState)
  const { text, todos } = state;
  const onChange = (e) => {
    dispatch({
      type: "CHANGE_INPUT",
      text: e.target.value
    })
    console.log(e.target.value)
  }
  const nextId = useRef(4);
  const onCreate = () => {
       dispatch({
      type: "CREATE_TODO",
      todo: {
        id: nextId.current,
        todotext: text,
        isDone: false,
      }
    })
  }
  const onDelete = (id) => {
    dispatch({
      type: "DELETE_TODO",
      id: id,
    })
  }
  const onToggle = (id) => {
    dispatch({
      type: "ISDONE_TODO",
      id: id
    })
  }
  return (
      <div className="App">
        <CreateTodo text = {text} onChange={onChange} onCreate={onCreate}/>
        <TodoLists todos={todos} onDelete={onDelete} onToggle={onToggle}/>
      </div>
    );
} 

export default App;

 

TodoList.js

import React from 'react';

//rsc
const TodoList = ({todo, onDelete, onToggle}) => {
    return (
        <div id="todo">
             <span id="todotodo" className={todo.isDone ? 'isDone' : ""} 
             onClick ={()=> onToggle(todo.id)}>
                {todo.todotext}
                </span> 
            <button id="delBtn" onClick={()=>{onDelete(todo.id)}}>X</button>
        </div>
        // className={todo.isDone && 'isDone'} 
    );
};

export default TodoList;

 

TodoLists.js

import React from 'react';
import TodoList from './TodoList';
import './TodoList.css'

const TodoLists = ({todos, onDelete, onToggle}) => {
    return (
        <div className='lists'>
            {todos.map(todo=><TodoList onToggle={onToggle} todo={todo} key={todo.id} onDelete={onDelete}/>)} 
        </div>
    );
};

export default TodoLists;

 

TodoList.css

*{padding: 0; margin: 0 auto; box-sizing: border-box;}
header {
    background-image: linear-gradient(135deg, #d2f985 0%, #fdd2c8 100%);
    width: 900px;
    height: 140px;
}
h2 {
    padding-top: 25px;
    padding-bottom: 8px;
    color: #222;
}
#todo_box {
    display: flex;
    align-items: center;
}
input {
    width: 600px;
    height: 28px;
    padding-left: 10px;
    border-radius: 25px;
    outline: none;
    border: none;
    margin-right: -120px;
}
.lists {
    width: 900px;
    background-color: #eee;
    padding: 8px 0;
    padding-left: 90px;
    text-align: left;
    line-height: 2.5;
}
button {
    padding: 0px 8px;
    border-radius: 25px;
    border: none;
    outline: none;
    background-color: #fff;
    font-size: 24px;
    cursor: pointer;
}
#todo {
    display: flex;
}
#todotodo {
    margin-left: 0px;
    cursor: pointer;
}
#delBtn {
    font-size: 16px;
    background-color: transparent;
    margin-right: 80px;
}
.active {
    text-decoration: line-through;
}
.isDone {
    background-color: lightgoldenrodyellow;
}

'Stack > React' 카테고리의 다른 글

[React] 상태관리 (useState / useReducer)  (0) 2022.06.24
[React] React Component Styling  (0) 2022.06.23
[React] 라이프 사이클 메서드(Life Cycle Method)  (0) 2022.06.21
[React] event-react(Event / ref)  (0) 2022.06.21
[React] 컴포넌트  (0) 2022.06.20
'Stack/React' 카테고리의 다른 글
  • [React] 상태관리 (useState / useReducer)
  • [React] React Component Styling
  • [React] 라이프 사이클 메서드(Life Cycle Method)
  • [React] event-react(Event / ref)
7ingout
7ingout
  • 7ingout
    Hello, 7ingout world!
    7ingout
  • 전체
    오늘
    어제
    • 분류 전체보기 (205)
      • Project (5)
      • Stack (173)
        • React (40)
        • JavaScript (50)
        • TypeScript (14)
        • HTML (11)
        • CSS (31)
        • Spring (9)
        • PHP (15)
        • SQL (3)
        • Python (0)
      • ETC (9)
      • Design (13)
        • Illustrator (6)
        • Photoshop (7)
      • Articloid (4)
        • 7ingout (4)
  • 공지사항

    • ☻
  • 인기 글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.0
7ingout
[React] to-do list
상단으로

티스토리툴바