본문 바로가기
Front-end/React\RN

리액트 to-do-list 흐름 파악

by javapp 자바앱 2022. 6. 5.
728x90

 

 

 

 

 

 

 

App.js

import { Component } from "react";
import Form from "./components/Form";
import TodoItemList from "./components/TodoItemList";
import TodoListTemplate from "./components/TodoListTemplate";

class App extends Component {
  id = 4;
  
  // 초기 데이터 정보
  state = {
    input: '',
    todos: [
      { id: 0, text: '할일1', checked: false },
      { id: 1, text: '할일2', checked: true },
      { id: 2, text: '할일3', checked: false },
      { id: 3, text: '할일4', checked: true }
    ]
  }

state 초기 데이터 생성

 

 

render

  render() {
    return (
      <div>
        <TodoListTemplate
          form={
            <Form value={this.state.input}
              onKeyPress={this.handleKeyPress}
              onChange={this.handleChange}
              onCreate={this.handleCreate}
            />
          }>
          <TodoItemList
            todos={this.state.todos}
            onRemove={this.handelRemove}
            onToggle={this.handelToggle} />

        </TodoListTemplate>
      </div >
    )
  }
}
export default App;

 

 

 

 

Form.js

import './Form.css'

const Form = ({ value, onKeyPress, onChange, onCreate }) => {
  return (
    <div className="form">

      <input value={value}
        onChange={onChange}
        onKeyPress={onKeyPress} />
      <div className='create-button' onClick={onCreate}>추가</div>
    </div>
  )
}
export default Form;

const Form = ({ value, onKeyPress, onChange, onCreate }) => {

 

 

TodoListTemplate.js

import './TodoListTemplate.css'

const TodoListTemplate = ({ form, children }) => {
  return (
    <main className='todo-list-template'>
      <div className='title'>오늘 할 일</div>
      <section className="form-wrapper">{form} </section>
      <section className="todos-wrapper">{children} </section>
    </main>
  )

}

export default TodoListTemplate;

 

TodoItemList.js

import { Component } from "react";
import TodoItem from "./TodoItem";

class TodoItemList extends Component {
  render() {
    const { todos, onRemove, onToggle } = this.props
    const todoList = todos.map(({ id, text, checked }) => (
      <TodoItem
        key={id}
        id={id}
        text={text}
        checked={checked}
        onRemove={onRemove}
        onToggle={onToggle} />
    ))
    return (
      <div>
        {todoList}
      </div>
    )
  }
}

export default TodoItemList;
App.js 에서 컴포넌트 호출
          <TodoItemList
            todos={this.state.todos}
            onRemove={this.handelRemove}
            onToggle={this.handelToggle} />
 
TodoItemList.js 에서 this.props 으로 값을 각각 받는다.
    const { todos, onRemove, onToggle } = this.props
 

TodoItem 으로 map (반복문을 통해) 각각 생성

    const todoList = todos.map(({ id, text, checked }) => (
      <TodoItem
        key={id}
        id={id}
        text={text}
        checked={checked}
        onRemove={onRemove}
        onToggle={onToggle} />
    ))

 

 

TodoItem.js

import { Component } from "react";
import './TodoItem.css';

class TodoItem extends Component {
  render() {
    const { text, checked, id, onRemove, onToggle } = this.props
    return (
      <div className="todo-item"
        onClick={() => onToggle(id)}>
        <div className="remove"
          onClick={e => {
            e.stopPropagation();
            onRemove(id)
          }
          }>
          &times;
        </div >
        <div className="{`todo-text ${checked && 'checked'}`}">
          <div> {text}</div>
        </div>
        {checked && <div className="check-mark">&#x2713;</div>}
      </div >

    )
  }
}

export default TodoItem;

    const { text, checked, id, onRemove, onToggle } = this.props

 

      <TodoItem
        key={id}
        id={id}
        text={text}
        checked={checked}
        onRemove={onRemove}
        onToggle={onToggle} />

TodoItem 을 호출할 때의 변수 순서와는 관계 없이 받을 수 있나보다

 

아이템 선택시 onClick 바로 실행-> 토글 onToggle(id) 호출, id를 넘겨준다.

      <div className="todo-item"
        onClick={() => onToggle(id)}>
 

 

아이템 삭제표시

        <div className="remove"
          onClick={e => {
            e.stopPropagation();  // 이벤트 전파 방지
            onRemove(id)
          }
          }>
          &times; //
        </div >

 

아이템 체크 표시

        <div className="{`todo-text ${checked && 'checked'}`}">
          <div> {text}</div>
        </div>
        {checked && <div className="check-mark">&#x2713;</div>}

 

`` 백틱  : 문자와 문자열 연결시 활용

 

 

 

 


Form

 

폼 태그 데이터 입력

  // 폼 태그에 글쓰기 가능 , state내 input에 값이 들어간다. -> value={this.state.input}
  handleChange = e => {
    this.setState({
      input: e.target.value
    })
  }
              onChange={this.handleChange}
input :  ...   // -> input = ...

 

 

 


 

 

  //토클
  handelToggle = (id) => {
    const { todos } = this.state // todos

    const index = todos.findIndex(todo => todo.id === id) //1
    const selected = todos[index] // { id: 1, text: '치킨먹기2', checked: true }

    const nextTodos = [...todos] //  { id: 1, text: '할일2', checked: true },
    nextTodos[index] = {
      ...selected, // 기존 데이터 유지 { id: 1, text: '할일2', checked: true },
      checked: !selected.checked  // 변경될 데이터만 새로 입력
    }

    // state 상태 변경은 setSate 필수
    this.setState({ 
      todos: nextTodos
    })
  }

   nextTodos[index] = {
      ...selected, // 기존 데이터 유지 { id: 1, text: '할일2', checked: true },
      checked: !selected.checked  // 변경될 데이터만 새로 입력
    }

 

 


 

할일 추가

  //입력하고 엔터키
  handleKeyPress = e => {
    if (e.key == 'Enter') { //입력된 키값 검사
      this.handleCreate()
    }
  }

  //추가
  handleCreate = () => {
    const { input, todos } = this.state
    this.setState({
      input: '',
      todos: todos.concat({ //concat 으로 값 추가
        id: this.id++,      // 아이디 +1 추가
        text: input,        // input: e.target.value  : 입력된 값이 들어간다.
        checked: false
      })
    })
  }

 

 

할일 삭제

  //삭제
  handelRemove = id => {
    
    console.log("id : " + id)
    const { todos } = this.state
    const nextTodos = todos.filter(todo => todo.id !== id)

    this.setState({
      todos: nextTodos
    })
  }

 

 

 

 

 

 

 

 

전체 코드

더보기
import { Component } from "react";
import Form from "./components/Form";
import TodoItemList from "./components/TodoItemList";
import TodoListTemplate from "./components/TodoListTemplate";


class App extends Component {
  id = 4;
 
  // 초기 데이터 정보
  state = {
    input: '',
    todos: [
      { id: 0, text: '할일1', checked: false },
      { id: 1, text: '할일2', checked: true },
      { id: 2, text: '할일3', checked: false },
      { id: 3, text: '할일4', checked: true }
    ]
  }


  // 폼 태그에 글쓰기 가능 , state내 input에 값이 들어간다. -> value={this.state.input}
  handleChange = e => {
    this.setState({
      input: e.target.value
    })
  }


  //토클
  handelToggle = (id) => {
    const { todos } = this.state // todos


    const index = todos.findIndex(todo => todo.id === id) //1
    const selected = todos[index] // { id: 1, text: '치킨먹기2', checked: true }


    const nextTodos = [...todos] //  { id: 1, text: '할일2', checked: true },
    nextTodos[index] = {
      ...selected, // 기존 데이터 유지 { id: 1, text: '할일2', checked: true },
      checked: !selected.checked  // 변경될 데이터만 새로 입력
    }


    // state 상태 변경은 setSate 필수
    this.setState({
      todos: nextTodos
    })
  }


  //입력하고 엔터키
  handleKeyPress = e => {
    if (e.key == 'Enter') { //입력된 키값 검사
      this.handleCreate()
    }
  }


  //추가
  handleCreate = () => {
    const { input, todos } = this.state
    this.setState({
      input: '',
      todos: todos.concat({ //concat 으로 값 추가
        id: this.id++,      // 아이디 +1 추가
        text: input,        // input: e.target.value  : 입력된 값이 들어간다.
        checked: false
      })
    })
  }


  //삭제
  handelRemove = id => {
   
    console.log("id : " + id)
    const { todos } = this.state
    const nextTodos = todos.filter(todo => todo.id !== id)


    this.setState({
      todos: nextTodos
    })
  }
 
  render() {
    return (
      <div>
        <TodoListTemplate
          form={
            <Form value={this.state.input}
              onKeyPress={this.handleKeyPress}
              onChange={this.handleChange}
              onCreate={this.handleCreate}
            />
          }>
          <TodoItemList
            todos={this.state.todos}
            onRemove={this.handelRemove}
            onToggle={this.handelToggle} />


        </TodoListTemplate>
      </div >
    )
  }
}
export default App;

 

 


 

 

props

여러 매개변수 대표로 받음

 

import './ExpenseItem.css';

function ExpenseItem(props){
    return (
        <div className='expense-item'>
            <div>2022 12 03</div>
            <div className='expense-item__description'>
                <h2>{props.title}</h2>
                <div className='expense-item__price'>{props.amount}</div>
            </div>
        </div>
    )
}

export default ExpenseItem;

 

 

import ExpenseItem from "./components/ExpenseItem";

function App() {
  const expenses = [
    {
      id: 'e1',
      title: 'Toilet Paper',
      amount: 94.12,
      date: new Date(2020, 7, 14),
    },
    { id: 'e2', title: 'New TV', amount: 799.49, date: new Date(2021, 2, 12) },
    {
      id: 'e3',
      title: 'Car Insurance',
      amount: 294.67,
      date: new Date(2021, 2, 28),
    },
    {
      id: 'e4',
      title: 'New Desk (Wooden)',
      amount: 450,
      date: new Date(2021, 5, 12),
    },
  ];
  return (
    <div>
      <h2>started</h2>
      <ExpenseItem
        title={expenses[0].title}
        amount={expenses[0].amount}
      />
    </div>
  );
}

export default App;

댓글