๐Ÿค ์€์ง€log ๐Ÿค

[REACT] To-do List ๋งŒ๋“ค๊ธฐ ๋ณธ๋ฌธ

๐Ÿ’™ React

[REACT] To-do List ๋งŒ๋“ค๊ธฐ

Eun_zii 2022. 10. 6. 14:31

๐Ÿ’ก ํ˜ผ์ž์„œ ๋งŒ๋“ค์ˆ˜ ์—†๋‹ค๋ฉด ์—ฌ๋Ÿฌ๋ฒˆ ์—ฐ์Šตํ•ด๋ณด๊ธฐ ๐Ÿ’ก

 

import { useState, useRef } from 'react'
import styled, { css } from 'styled-components'

const Todo = () => {
  const [text, setText] = useState('')
  const [todoList, setTodoList] = useState([])
  const nextId = useRef(1)

  const handleChange = (e) => {
    setText(e.target.value)
  }
  const handleSubmit = (e) => {
    e.preventDefault()
    // form ์•ˆ์— submit ์—ญํ• ์„ ํ•˜๋Š” ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์–ด๋„ ์ƒˆ๋กœ๊ณ ์นจ ๋˜์ง€ ์•Š๊ฒŒ ํ•˜๊ณ ์‹ถ์„ ๋•Œ (submit์€ ์ž‘๋™๋จ)
    console.log(text)
    const newTodoList = [
      ...todoList,
      { id: nextId.current, text, isDone: false },
    ]
    setTodoList(newTodoList)
    setText('')
    nextId.current += 1
  }
  const handleDelete = (id) => {
    const newTodoList = todoList.filter((todo) => todo.id !== id)
    setTodoList(newTodoList)
  }

  const handleIsDone = (id, checked) => {
    const newTodoList = todoList.map((todo) =>
      todo.id === id ? { ...todo, isDone: checked } : todo,
    )
    setTodoList(newTodoList)
  }

  return (
    <Container>
      <Title>๐Ÿงธ ์€์ง€์˜ To-do List ๐Ÿงธ</Title>
      <form onSubmit={handleSubmit}>
        <InputWrapper>
          <InputText
            placeholder="ํ•  ์ผ์„ ์ž…๋ ฅํ•˜์„ธ์š”."
            onChange={handleChange}
            value={text}
          />
          <BtnSubmit>+</BtnSubmit>
        </InputWrapper>
      </form>
      <List>
        {todoList.map(({ id, text, isDone }, i) => (
          <Item key={i} isDone={isDone}>
            <label>
              <Checkbox
                type="checkbox"
                onChange={(e) => handleIsDone(id, e.target.checked)}
              />
              <Content>{text}</Content>
            </label>
            <BtnDelete onClick={() => handleDelete(id)}>-</BtnDelete>
          </Item>
        ))}
      </List>
    </Container>
  )
}

const Container = styled.div`
  width: 500px;
  margin: 60px auto;
  background: #fff;
  min-height: 500px;
`
const Title = styled.div`
  text-align: center;
  font-size: 24px;
  font-weight: bold;
  padding: 20px;
  background: #fdc7d0;
  color: #fff;
`
const InputWrapper = styled.div`
  height: 40px;
  background-color: black;
  display: flex;
`
const InputText = styled.input`
  flex: 1;
  background-color: #fff;
  color: #000;
`
const BtnSubmit = styled.button`
  background: gray;
  border: none;
  color: white;
  height: 100%;
  width: 40px;
  font-size: 30px;
`
const List = styled.ul`
  list-style: none;
  margin: 0;
  padding: 0; 
` /* โญ๏ธ ul์„ ๋‹ค๋ฃฐ๋•Œ ํ•ญ์ƒ ์‚ฌ์šฉํ•ด์ค˜์•ผํ•จ โญ๏ธ */
const Content = styled.span``
const Item = styled.li`
  height: 60px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  & + & {
    border-top: 1px solid #ddd;
  }
  background-color: ${({ isDone }) => isDone && 'lightgray'};

  ${({ isDone }) =>
    isDone &&
    css`
      ${Content} {
        text-decoration: line-through;
        color: #000;
      }
    `}
`
const Checkbox = styled.input`
  margin: 20px;
`
const BtnDelete = styled.button`
  border-radius: 50%;
  border: 2px solid darkgray;
  background: #fff;
  color: darkgray;
  cursor: pointer;
  margin-right: 20px;
`

export default Todo
728x90

'๐Ÿ’™ React' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[REACT] SPA ์™€ async  (0) 2022.10.06
[REACT] useEffect๊ฐ€ 2๋ฒˆ์‹คํ–‰๋ ๋•Œ  (0) 2022.10.06
[REACT] Pagination ๊ณผ Querystring  (0) 2022.10.06
[REACT] Instagram _ Log-In  (0) 2022.10.06
[REACT] Naver ์ฑ… ๊ฒ€์ƒ‰  (0) 2022.10.06