본문 바로가기
ICIA 수업일지

2021.09.10 수업일지(React.js)

by 주성씨 2021. 9. 10.

- React.js

- 새로운 프로젝트를 만들어보겠다.

C:\data\react>yarn create react-app ex02

 

- 프로젝트 폴더로 이동

C:\data\react\ex02

 

- 프로젝트 시작

C:\data\react\ex02\yarn start

 

- C:\data\react\ex02\public\index.html -> html 시작 부분

- C:\data\react\ex02\src\index.js -> root 연결부 / App component render 연결부

- C:\data\react\ex02\src\App.css -> 웹 CSS부분

- C:\data\react\ex02\src\App.js -> 웹 선언부분

import './App.css';
import Foods from './component/Foods';

// 함수형 컴포넌트(화살표형으로 전환)
const App = () => {
  return (
    <div className="App">
      <Foods/>
    </div>
  );
}

export default App;

 

- C:\data\react\ex02\src\(new)component

- C:\data\react\ex02\src\component\(new)Foods.js

const Foods = () =>{
    return(
        <div>
            <h1>음식목록</h1>
        </div>
    )
}
export default Foods;

 

확인

 

- 음식목록에 들어갈 배열을 만들어 출력해보자.

- C:\data\react\ex02\src\component\Foods.js

import { useState } from "react";

const Foods = () =>{
    // 변수 변경은 setfoods로
    const [foods, setfoods] = useState([
        {id:1,name:'족발'},
        {id:2,name:'보쌈'},
        {id:3,name:'탕슉'},
        {id:4,name:'수육'}
    ]);
    return(
        <div>
            <h1>음식목록</h1>
            <div>
                {foods.map((food)=><h3 key={food.id}>{food.name}</h3>)}
            </div>
        </div>
    )
}
export default Foods;

확인

 

- input tag로 배열에 추가해보자.

- C:\data\react\ex02\src\component\Foods.js

import { useState } from "react";

const Foods = () =>{
    // 변수 변경은 setfoods로
    const [foods, setfoods] = useState([
        {id:1,name:'족발'},
        {id:2,name:'보쌈'},
        {id:3,name:'탕슉'},
        {id:4,name:'수육'}
    ]);
    
    const [name,setName] = useState('만두');

    const [nextId, setNextId] = useState(5);

    const onClickAdd = () =>{
        // concat 연결하겠다.
        const newFoods = foods.concat({
            id: nextId, name: name
        });
        setfoods(newFoods);
        setNextId(nextId+1);
        setName('');
    }
    const onKeyPressName = (e) =>{
        if(e.key==='Enter'){
            onClickAdd();
        }
    }

    return(
        <div>
            <h1>음식목록</h1>
            {/* onchage할때마다 setName한다. */}
            <input type="text" value={name} onChange={(e)=>setName(e.target.value)}
            onKeyPress={onKeyPressName}/>
            <button onClick={onClickAdd}>추가</button>
            {name}
            <div>
                {foods.map((food)=><h3 key={food.id}>{food.id}:{food.name}</h3>)}
            </div>
        </div>
    )
}
export default Foods;

 

확인

 

- <h3> 더블클릭하면 삭제하는 메서드를 만들어보도록 하겠다.

    const onRemove = (id,name) => {
        if(!window.confirm(`${name}을(를) 삭제하시겠습니까?`)) return;
        const newFoods = foods.filter(food => food.id !== id);
        setfoods(newFoods);
    }
            <div>
                {foods.map((food)=><h3 key={food.id} 
                onDoubleClick={()=>onRemove(food.id, food.name)}>{food.id}:{food.name}</h3>)}
            </div>

 

확인

 

- 이름, 전화번호, 주소 입력받아 추가하는 컴포넌트를 만들어보겠다.

- C:\data\react\ex02\src\component\(new)Address.js -> parent

import React, { useState } from 'react';
import Person from './Person';
const Address = () => {
    const [persons, setPersons] = useState([
        {id:1,name:'김철수',tel:'032-123-4567',address:'인천시 미추홀구 학익동'},
        {id:2,name:'이영희',tel:'032-890-1234',address:'인천시 부평구 청천동'},
        {id:3,name:'박대준',tel:'032-567-8901',address:'인천시 중구 신포동'},
    ])
    return (
        <div>
            <h1>주소록</h1>
            <table>
                {persons.map((p)=><Person key={p.id} id={p.id} name={p.name} tel={p.tel} address={p.address}/>)}
            </table>
        </div>
    );
};

export default Address;

 

- C:\data\react\ex02\src\component\(new)person.js -> child

const Person = (props) => {
    const{id,name,tel,address} = props;
    return (
        <tr>
            <td><h3>{id}</h3></td>
            <td><h3>{name}</h3></td>
            <td><h3>{tel}</h3></td>
            <td><h3>{address}</h3></td>
        </tr>
    );
};

export default Person;

 

확인

 

- 입력추가하는 input tag를 만들고 값을 받아보겠다.

- C:\data\react\ex02\src\component\Address.js

import React, { useState } from 'react';
import Person from './Person';
const Address = () => {
    // 변수 배열
    const [persons, setPersons] = useState([
        {id:1,name:'김철수',tel:'032-123-4567',address:'인천시 미추홀구 학익동'},
        {id:2,name:'이영희',tel:'032-890-1234',address:'인천시 부평구 청천동'},
        {id:3,name:'박대준',tel:'032-567-8901',address:'인천시 중구 신포동'},
    ])

    // 변수 오브젝트
    const [form, setForm] = useState({
        name:'이주성',
        tel:'032-870-7720',
        address:'인천시 서구 검암동'
    })

    const {name,tel,address} = form;

    const onChange = (e) =>{
        const newForm ={
            ...form,
            [e.target.name]:e.target.value
        }
        setForm(newForm);
    }

    return (
        <div>
            <h1>주소록</h1>
            <div className="divInput">
                <input type="text" name="name" value={name} onChange={onChange}/><br/>
                <input type="text" name="tel" value={tel} onChange={onChange}/><br/>
                <input type="text" name="address" value={address} onChange={onChange} size={50}/><br/>
                <button>주소추가</button>
            </div>
            <table>
                {persons.map((p)=><Person key={p.id} id={p.id} name={p.name} tel={p.tel} address={p.address}/>)}
            </table>
        </div>
    );
};

export default Address;

 

확인

 

    const [nextId,setNextId] = useState(4);

    const onInsert = () =>{
        if(name===''){
            alert("이름을 입력하세요.")
            return;
        }
        if(!window.confirm("내용을 추가하시겠습니까?")) return;
        const newPersons=persons.concat({
            ...persons,
            id:nextId,
            name:name,
            tel:tel,
            address:address
        });
        setPersons(newPersons);
        setNextId(nextId+1);
        setForm({
            name:'',
            tel:'',
            address:''
        });
    }
    return (
...
                <button onClick={onInsert}>주소추가</button>
...
    );

확인

 

- 삭제 버튼을 추가하겠다.

- 값뿐만아니라 메서드나 이벤트도 넘겨줄 수 있다.

C:\data\react\ex02\src\component\Person.js

const Person = (props) => {
    const{id,name,tel,address,onRemove} = props;
    return (
        <tr>
...
            <button onClick={onRemove}>삭제</button>
        </tr>
    );
};

export default Person;

 

- C:\data\react\ex02\src\component\Address.js

import React, { useState } from 'react';
import Person from './Person';
const Address = () => {

...

    const onRemove =(id) =>{
        if(!window.confirm(`${id}을(를) 삭제하시겠습니까?`)) return;
        const newPersons = persons.filter(p => p.id !== id);
        setPersons(newPersons);
    }

    return (
        <div>
            <h1>주소록</h1>
            <div className="divInput">
...
            </div>
            <table>
                {persons.map((p)=><Person key={p.id} id={p.id} name={p.name} tel={p.tel} address={p.address} 
                onRemove={()=>onRemove(p.id)}/>)}
            </table>
        </div>
    );
};

export default Address;

 

확인

 

 

- 컴포넌트의 라이프사이클 메서드

  • 마운트: DOM이 생성되고 웹 브라우저상에 나타나는 것을 마운트라고 한다. 이때 호출되는 메서드는 다음과 같다. 1) constructor: 컴포넌트를 새로 만들 때마다 호출되는 클래스 생성자 메서드이다.
    2) render: 우리가 준비한 UI를 렌더링하는 메서드이다.
    3) componentDidMount: 컴포넌트가 웹 브라우저상에 나타난 후 호출하는 메서드이다.
  • 업데이트: pops가 바뀔 때, state가 바뀔 때, 부모 컴포넌트가 리렌더링될 때 다음 메서드를 호출한다.
    1) shouldComponentUpdate: props 또는 state를 변경했을 때 컴포넌트가 리렌더링을 해야 할지 말아야 할지를 결정하는 메서드이다.
    2) render: 컴포넌트를 리렌더링 한다.
    3) componentDidUpdate: 컴포넌트의 업데이트 작업이 끝난 후 호출하는 메서드이다.
  • 언마운트: 마운트의 반대 과정, 즉 컴포넌트를 DOM에서 제거하는 것을 언마운트라고 한다. componentWillUnmount: 컴포넌트가 웹 브라우저상에서 사라지기 전에 호출하는 메서드이다.

생명주기 상태도

 

- class 함수를 이용해 jsonplaceholder의 todos 데이터를 가지고와 특정 아이디를 가지는 데이터를 불러와보도록 하겠다.

https://jsonplaceholder.typicode.com/todos

 

- C:\data\react\ex02\src\component\(new)Api.js

import React, { Component } from 'react';

class Api extends Component {
    // 생성자에 변수 정의
    constructor(props){
        super(props);
        this.state ={
            data:''
        }
    }

    // 데이터 불러와 변수에 넣기
    callAPI = ()=>{
        fetch('https://jsonplaceholder.typicode.com/todos/1')
        .then(res => res.json())
        .then(json => {
            this.setState({
                data:json.title
            })
        });
    }

    // render 함수가 실행된 후 싱행
    componentDidMount(){
        this.callAPI();
    }

    render() {
        return (
            <div>
                <h1>오늘의 할일</h1>
                <hr/>
                <h3>{this.state.data ? this.state.data:'데이터를 불러오는 중입니다.'}</h3>
            </div>
        );
    }
}

export default Api;

 

확인

 

- 함수형을 이용해 위와 마찬가지로 데이터를 불러와 출력해보도록 하겠다. 다만 검색란을 이용해 특정 데이터를 웹에서 입력하여 찾을 수 있도록 하겠다.

- C:\data\react\ex02\src\component\(new)Api1.js

import { useEffect, useState } from "react";

const Api1 = () => {
    const [data,setData] = useState('');
    const [number,setNumber] = useState(1);

    const callAPI = ()=>{
        fetch(`https://jsonplaceholder.typicode.com/todos/${number}`)
        .then(res => res.json())
        .then(json => {
            setData(json.title);
        });
    }

    useEffect(()=>{
        callAPI();
    },[number]);

    return(
        <div>
            <h1>오늘의 할일(함수형)</h1>
            <input type="text" value={number} size={3} onChange={(e)=>setNumber(e.target.value)}/>
            <button>검색</button>
            <h3>{data ? data:'데이터를 불러오는 중입니다.'}</h3>
        </div>       
    )
};

export default Api1;

 

확인

 

 

- 컴포넌트 스타일링

리엑트에서 DOM 요소에 스타일을 적용할 때는 문자열 형태로 넣는 것이 아니라 객체 형태로 넣어 주어야 한다. 스타일 이름 중에 - 문자가 포함되 는 있으면 - 문자를 없애고 카멜 표기법으로 작성해야 한다. 따라서 background-color는 backgroundColor로 작성한다.

 

- style 다이렉트로 표현하는 방법 2가지

- C:\data\react\ex02\src\component\Hello.js

const Hello = () => {
    return(
        //direct CSS속성은 {{}}에 넣어야 하고 오브젝트 속성이라
        //아래와 같이 한다.
        //padding-top을 paddingTop로 camelCase로 줘야한다. 이와 같이 조금씩 다르다.
        <div>
            <h1 style={{background:'black', color:'white',paddingTop:'50px', paddingBottom:'50px'}}>Hello World!</h1>
        </div>
    )
}
export default Hello;

or

const Hello = () => {
    const style= {background:'black', color:'white',paddingTop:'50px', paddingBottom:'50px'}
    return(
        //direct CSS속성은 {{}}에 넣어야 하고 오브젝트 속성이라
        //아래와 같이 한다.
        //padding-top을 paddingTop로 camelCase로 줘야한다. 이와 같이 조금씩 다르다.
        <div>
            <h1 style={style}>Hello World!</h1>
        </div>
    )
}
export default Hello;

 

 

- 일정관리 웹 애플리케이션 만들기

- TodoTemplate

- C:\data\react\ex02\src\component\(new)TodoTemplate.js

import React from 'react';

const TodoTemplate = ({children}) => {
    return (
        <div className="TodoTemplate">
            <div className="app-title">일정관리</div>
            <div className="content">{children}</div>
        </div>
    );
};

export default TodoTemplate;

 

- C:\data\react\ex02\src\App.js

import './App.css';
import TodoTemplate from './component/TodoTemplate';

const App = () => {
  return (
    <div className="App">
      <TodoTemplate>
        {/* children 부분 */}
        <h1>일정관리</h1>
        <h2>이주성</h2>
      </TodoTemplate>
    </div>
  );
}

export default App;

 

- C:\data\react\ex02\src\component\(new)css\(new)TodoTemplate.css

body {
    margin: 0px;
    padding: 0px;
    background: #e9ecef;
}

.TodoTemplate {
    width: 512px;
    /*width가 주어진 상태에서 좌우 중앙 정렬*/
    margin: 0px auto;
    margin-top: 6rem;
    border-radius: 4px;
    overflow: hidden;
}

.app-title {
    background: #22b8cf;
    color: white;
    height: 4rem;
    font-size: 1.5rem;
    /*내용물의 세로 가운데 정렬*/
    align-items: center;
    /*내용물의 가로 가운데 정렬*/
    justify-content: center;
    display: flex;
}

.content {
    background: white;
}

 

- TodoInsert

- C:\data\react\ex02\src\component\(new)TodoInsert.js

import React from 'react';
import {MdAdd} from 'react-icons/md';

const TodoInsert = () => {
    return (
        <form className="TodoInsert">
            <input placeholder="할일을 입력하세요." />
            <button type="submit"><MdAdd/></button>
        </form>
    );
};

export default TodoInsert;

 

- TodoInsert css를 추가해준다.

- C:\data\react\ex02\src\component\css\TodoTemplate.css

.TodoInsert {
    display: flex;
    background: #495057;
}

/*기본 스타일 초기화*/
input {
    background: none;
    outline: none;
    border: none;
    padding: 0.5rem;
    font-size: 1.125rem;
    line-height: 1.5;
    color: white;
    /*버튼을 제외한 영역을 모두 차지하기*/
    flex: 1;
}

input::placeholder {
    color: #dee2e6;
}

/*기본 스타일 초기화*/
button {
    background: none;
    outline: none;
    border: none;
    background: #868e96;
    color: white;
    padding-left: 1rem;
    padding-right: 1rem;
    font-size: 1.5rem;
    align-items: center;
    cursor: pointer;
}

 

- 터미널을 중지(ctrl + c)시키고 다음과 같이 입력한다.

C:\data\react\ex02>yarn add react-icons

 

- 설치가 완료 후 다시 시작한다.

yarn start

 

확인

 

- TodoList와 TodoListItem을 만들자.

- C:\data\react\ex02\src\component\(new)TodoListItem.js

import React from 'react';

const TodoListItem = () => {
    return (
        <div>
            할일
        </div>
    );
};

export default TodoListItem;

 

- C:\data\react\ex02\src\component\(new)TodoList.js

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

const TodoList = () => {
    return (
        <div>
            <TodoListItem/>
            <TodoListItem/>
            <TodoListItem/>
        </div>
    );
};

export default TodoList;

 

- C:\data\react\ex02\src\App.js

...

const App = () => {
  return (
    <div className="App">
      <TodoTemplate>
        {/* children 부분 */}
        <TodoInsert/>
        <TodoList/>
      </TodoTemplate>
    </div>
  );
}

...

 

할일

 

- app.js에서 지정한 변수값들을 todolistitem으로 보내도록 하겠다.

- C:\data\react\ex02\src\App.js

...

const App = () => {
  const[todos,setTodos] = useState([
...
    {id:4,text:'API 호출',checked: false} // 추가
  ]);
  return (
    <div className="App">
...
        <TodoList todos={todos}/>
...
    </div>
  );
}

export default App;

 

- C:\data\react\ex02\src\component\TodoList.js

...
const TodoList = ({todos}) => {
    return (
        <div>
            {todos.map(todo => <TodoListItem key={todo.id} todo={todo}/>)}
        </div>
    );
};
...

 

- C:\data\react\ex02\src\component\TodoListItem.js

import React from 'react';
import { MdCheckBox, MdCheckBoxOutlineBlank, MdRemoveCircleOutline } from 'react-icons/md';

const TodoListItem = ({todo}) => {
    const {text,checked} =todo;
    return (
        <div className="TodoListItem">
            <div className={checked? "checkbox_checked":"checkbox"}>
                {checked ? <MdCheckBox/>:<MdCheckBoxOutlineBlank/>}
                <div className="text">{text}</div>
            </div>
            <div className="remove">
                <MdRemoveCircleOutline/>
            </div>
        </div>
    );
};

export default TodoListItem;

 

- C:\data\react\ex02\src\component\css\TodoTemplate.css

/* 리스트 CSS */
.TodoList {
    min-height: 320px;
    max-height: 513px;
    overflow: auto;
}

.TodoListItem {
    padding: 1rem;
    display: flex;
    align-items: center;
    /*엘리먼트 사이사이에 테두리를 넣어 줌*/
    border-top: 1px solid #dee2e6;
}

.TodoListItem:nth-child(even) {
    background: #f8f9fa;
}

svg {
    /*아이콘*/
    font-size: 1.5rem;
    margin-right: 0.5rem;
}

.checkbox,
.checkbox_checked {
    cursor: pointer;
    /*차지할 수 있는 영역 모두 차지*/
    flex: 1;
    display: flex;
    align-items: center;
}

.checkbox_checked svg {
    color: #22b8cf;
}

.checkbox_checked .text {
    color: #adb5bd;
    text-decoration: line-through;
}

.remove {
    cursor: pointer;
    color: #ff6b6b;
}

 

확인

 

 

- 값을 입력받아 list를 추가해보겠다.

- todoinsert에 있던 변수와 form을 app.js로 옮기겠다. useCallback은 아직 안배워서 나중에 해보도록 하겠다.

import './App.css';
import { useRef, useState } from 'react';
...
import {MdAdd} from 'react-icons/md';

...

// 변수 선언 리퍼런스
const [nextId,setNextId] = useState(5);

...

const onClickSubmit = (e) =>{
  e.preventDefault();
  if(!window.confirm('추가하시겠습니까?')) return;
  const newTodos = todos.concat({
    ...todos,
    id:nextId,
    text:value,
    checked:false
  });
  setTodos(newTodos);
  setNextId(nextId+1);
  setValue('');
}

  return (
    <div className="App">
      <TodoTemplate>
        <form className="TodoInsert">
            <input placeholder="할일을 입력하세요."  value={value} onChange={onChange}/>
            <button onClick={onClickSubmit}><MdAdd/></button>
        </form>
        <TodoList todos={todos}/>
      </TodoTemplate>
    </div>
  );
};

export default App;

 

확인

 

- 엔터로 입력을 받고 싶다면

...

const onKeyPress=(e)=>{
  if(e.key==='Enter'){
    onClickSubmit();
  }
}

  return (
    <div className="App">
      <TodoTemplate>
        <form className="TodoInsert">
            <input placeholder="할일을 입력하세요."  value={value} onChange={onChange}
            onKeyPress={onKeyPress}/>
            <button onClick={onClickSubmit}><MdAdd/></button>
        </form>
        <TodoList todos={todos}/>
      </TodoTemplate>
    </div>
  );
};

export default App;

 

확인

 

- 다시

- CSS 빼고 전부 삭제

- C:\data\react\ex02\src\App.js

import './App.css';
import TodoList from './component/TodoList';

const App = () => {

  return (
    <div className="App">
      <TodoList>
        
      </TodoList>
    </div>
  );
};

export default App;

 

- C:\data\react\ex02\src\component\(new)TodoList.js

import React, { useState } from 'react';
import './css/TodoTemplate.css'
import {MdAdd} from "react-icons/md"
import TodoListItem from './TodoListItem';

const TodoList = () => {

    const [todos,setTodos] = useState([
        {id:1, text:'리액트 기초',checked:true},
        {id:2, text:'리액트 중급',checked:true},
        {id:3, text:'리액트 실전',checked:false},
        {id:4, text:'리액트 UI',checked:false},
    ]);

    return (
        <div className="TodoTemplate">
            <div className="app-title">일정관리</div>
            <div className="content">

                <div className="TodoInsert">
                    <input placeholder="일정을 입력하세요."/>
                    <button><MdAdd/></button>
                </div>

                {todos.map(todo=><TodoListItem key={todo.id} todo={todo}/>)}

            </div>
        </div>
    );
};

export default TodoList;

 

- C:\data\react\ex02\src\component\TodoListItem.js

import React from 'react';
import { MdCheckBox, MdCheckBoxOutlineBlank, MdRemoveCircleOutline } from 'react-icons/md';

const TodoListItem = ({todo}) => {
    const{text,checked}=todo;
    return (
        <div className="TodoListItem">
            <div className={ checked ? "checkbox_checked": "checkbox" }>
                { checked ? <MdCheckBox/> :<MdCheckBoxOutlineBlank/> }
                <div className="text">{ text }</div>
            </div>
            <div className="remove">
                <MdRemoveCircleOutline/>
            </div>
        </div>
    );
};

export default TodoListItem;

 

확인

 

- C:\data\react\ex02\src\component\TodoList.js

import React, { useState } from 'react';
import './css/TodoTemplate.css'
import {MdAdd} from "react-icons/md"
import TodoListItem from './TodoListItem';

const TodoList = () => {

    const [todos,setTodos] = useState([
        {id:1, text:'리액트 기초',checked:true},
        {id:2, text:'리액트 중급',checked:true},
        {id:3, text:'리액트 실전',checked:false},
        {id:4, text:'리액트 UI',checked:false},
    ]);

    const [value,setValue] = useState('');
    const [nextId,setNextId] = useState(5);

    const onInsert = () => {
        const newTodos = todos.concat({
            ...todos,
            id:nextId,
            text:value,
            checked:false
        });
        setTodos(newTodos);
        setNextId(nextId+1);
        setValue('');
    }

    const onKeyPress = (e) =>{
        if(e.key==='Enter'){
            onInsert();
        }
    }

    return (
        <div className="TodoTemplate">
            <div className="app-title">일정관리</div>
            <div className="content">

                <div className="TodoInsert">
                    <input placeholder="일정을 입력하세요." value={value} 
                    onChange={(e)=>setValue(e.target.value)}
                    onKeyPress={onKeyPress}/>
                    <button onClick={onInsert}><MdAdd/></button>
                </div>

                {todos.map(todo=><TodoListItem key={todo.id} todo={todo}/>)}

            </div>
        </div>
    );
};

export default TodoList;

 

확인

 

- 이제 삭제해보도록 하겠다.

- C:\data\react\ex02\src\component\TodoList.js

...

    const onRemove =(id) =>{
        if(!window.confirm(`${id}번 일정을 삭제하시겠습니까?`)) return;
        // 같지 않은 것만 걸러내겠다. 같은건 안걸러내겠다.
        const newTodos = todos.filter((todo)=>todo.id!==id);
        setTodos(newTodos);
    }

    return (
        <div className="TodoTemplate">
            <div className="app-title">일정관리</div>
            <div className="content">
...
                {todos.map(todo=><TodoListItem key={todo.id} todo={todo} 
                onRemove={()=>onRemove(todo.id)}/>)}

            </div>
        </div>
    );
};

export default TodoList;

 

- C:\data\react\ex02\src\component\TodoListItem.js

...
    return (
        <div className="TodoListItem">
...
            <div className="remove">
                <MdRemoveCircleOutline onClick={onRemove}/>
            </div>
        </div>
    );
};

export default TodoListItem;

 

- 체크박스 토글

- C:\data\react\ex02\src\component\TodoList.js

...

    const onToggle = (id) => {
        setTodos(todos.map(todo => todo.id === id ? {...todo, checked:!todo.checked}:todo))
    }

    return (
        <div className="TodoTemplate">
            <div className="app-title">일정관리</div>
            <div className="content">
...

                {todos.map(todo=><TodoListItem key={todo.id} todo={todo} 
                onRemove={()=>onRemove(todo.id)} onToggle={()=>onToggle(todo.id)} />)}

            </div>
        </div>
    );
};

export default TodoList;

 

- C:\data\react\ex02\src\component\TodoListItem.js

import React from 'react';
import { MdCheckBox, MdCheckBoxOutlineBlank, MdRemoveCircleOutline } from 'react-icons/md';

const TodoListItem = ({todo,onRemove,onToggle}) => {
    const{text,checked}=todo;
    return (
        <div className="TodoListItem">
            <div className={ checked ? "checkbox_checked": "checkbox" } onClick={onToggle}>
                { checked ? <MdCheckBox/> :<MdCheckBoxOutlineBlank/> }
                <div className="text">{ text }</div>
            </div>
            <div className="remove">
                <MdRemoveCircleOutline onClick={onRemove}/>
            </div>
        </div>
    );
};

export default TodoListItem;

 

확인