개발/도서

TodoList 프론트엔드 서비스 개발 - 2

괴발자-K 2022. 8. 26. 13:24

Todo 추가 서비스

Todo 추가를 통해 이벤트 핸들러 함수를 구현하는 방법과 핸들러 함수를 UI에 연결

Todo 추가 모듈 생성

imoprt React from "react";
import {TextField, Paper Button, Grid} from "@material-ui/core";

class AddTodo extends React.Component {
   
    constructor(props) {
       super(props);
       this.state = {
           item : { title : ""}
       };
    }
    
    render(){
         return(
            <Paper style={{margin:16, padding: 16}}>
                <Grid container>
                     <Grid xs={11} md={11} item style={{ paddingRight:16 }}>
                         <TextFiled placeholder="Add Todo here" fullWidth />                     
                     </Grid>
                     <Grid xs={1} md={1} item>
                         <Button fullWidth color="secondary" variant="outlined">
                            +
                         </Button>
                     </Grid>
                </Grid>
            </Paper>
         )
    }
}

export default AddTodo;

 

 App.js에 AddTodo 컴포넌트 추가

import React from 'react';
import Todo from './Todo';
import AddTodo from './AddTodo';
import {Paper, List, Container} from "@material-ui/core";
import './App.css';



class App extends React.Component{

     constructor(props){
         super(props);
         this.state = {      
            items: [
                { id:"0", title: "Hello World 1", done: true},
                { id: "1", title: "Hello World 2", done: false},
            ],
         };
     }
     
     render(){
      
      //자바스크립트가 제공하는 map()을 이용해 배열을 반복해 <Todo /> 컴포넌트 생성
      const todoItems = this.state.items.length > 0 && 
         (
         <Paper style={{margin:16}}>
          <List>
            {this.state.items.map((item, idx) =>(
                <Todo item={item} key={item.id} />
            ))}
          </List>
         </Paper>
      )
      
      return( 
           <div className='App'>
              <Container maxWidth="md">
                  <AddTodo />
                  <div className="TodoList">{todoItems}</div>
              </Container>
           </div>

         )  
     }
}

export default App;

 

Add 핸들러 추가

import React from "react";
import {TextField, Paper, Button, Grid} from "@material-ui/core";

class AddTodo extends React.Component{
    constructor(props){
        super(props);
        this.state= {  // 사용자의 입려글 저장할 오브젝트 
            item: { title: ""}
        };
        this.add = props.add; //props의 함수를 this.add에 연결
    }

    //함수 작성
    onInputChange = (e) => {
        const thisItem  = this.state.item;
        thisItem.title = e.target.value;
        this.setState({item : thisItem});
        console.log(thisItem);
    }


     render(){

        return(
            <Paper style={{margin: 16, padding: 16}}>
               <Grid container>
                    <Grid xs={11} md={11} item style={{paddingRight: 16}}>
                        <TextField placeholder="Add Todo here" 
                        fullWidth onChange={this.onInputChange} 
                        value={this.state.item.title}
                        onKeyPress={this.enterKeyEventHandler}/>
                    </Grid>
                    <Grid xs={1} md={1} item>
                        <Button fullWidth color="secondary" variant="outlined" onClick={this.onButtonClick}>
                            +
                        </Button>
                    </Grid>
               </Grid>
            </Paper>
        );
     }
}

export default AddTodo;

onInputChange() ???

자바스크립트 함수다.  Event e를 매겨변수로 받는다. event 오브젝트는 어떤 일이 일어났을 때의 상태와 event가 발생했을 때 시점의 정보를 담고 있다.

 

Add 함수 작성

App컴포넌트는 items에 접근이 가능(AddTodo컴포넌트는 상위 컴포넌트의 items에 접근 X)

App컴포넌드에 add() 함수를 추가하고 AddTodo의 프로퍼티로 넘겨 AddTodo에서 사용한다.

 

import React from 'react';
import Todo from './Todo';
import AddTodo from './AddTodo';
import {Paper, List, Container, AppBar, Toolbar, Grid, Typography, Button} from "@material-ui/core";
import { call, signout } from './service/ApiService';
import './App.css';



class App extends React.Component{

     constructor(props){
         super(props);
         this.state = {      
            items: [
                { id: "0", title:"Hello World 1", done: true},
                { id: "1", title:"Hello World 2", done: false},
            ],
         };
     }

     함수 추가
    add = (item) => {
        const thisItem = this.state.items;
        item.id = "ID-" + thisItem.  ; // 키를 위한 id추가
        item.don = false;//done 초기화
        thisItem.push(item); // 리스트에 아이템 추가
        this.setState({ item : thisItem }); //업데이트는 반드시 this.setState로 해야함
        console.log("item : ", this.state.items);
    }

   
  

     render(){
      
      //자바스크립트가 제공하는 map()을 이용해 배열을 반복해 <Todo /> 컴포넌트 생성
      const todoItems = this.state.items.length > 0 && 
         (
         <Paper style={{margin:16}}>
          <List>
            {this.state.items.map((item, idx) =>(
                <Todo item={item} key={item.id} />
            ))}
          </List>
         </Paper>
      )
      
      // 선택한 content 렌더링
      return( 
           <div className='App'>
              <Container maxWidth="md">
                  <AddTodo add={this.add}/>
                  <div className="TodoList">{todoItems}</div>
              <Container>
           </div>

          );  
     }
}


export default App;

 

AddTodo.js에서 add함수 사용 및 Enter키 입력 시 아이템 추가

import React from "react";
import {TextField, Paper, Button, Grid} from "@material-ui/core";

class AddTodo extends React.Component{
    constructor(props){
        super(props);
        this.state= {  // 사용자의 입려글 저장할 오브젝트 
            item: { title: ""}
        };
        this.add = props.add; //props의 함수를 this.add에 연결
    }

    //함수 작성
    onInputChange = (e) => {
        const thisItem  = this.state.item;
        thisItem.title = e.target.value;
        this.setState({item : thisItem});
        console.log(thisItem);
    }

    // 함수 작성 클릭
    onButtonClick = () => {
        this.add(this.state.item); // add 함수 사용
        this.setState({
            item:{title:""}
        });
    }
    enterKeyEventHandler = (e) => {
       if(e.key === "Enter") this.onButtonClick();
    }


     render(){

        return(
            <Paper style={{margin: 16, padding: 16}}>
               <Grid container>
                    <Grid xs={11} md={11} item style={{paddingRight: 16}}>
                        <TextField placeholder="Add Todo here" 
                        fullWidth onChange={this.onInputChange} 
                        value={this.state.item.title}
                        onKeyPress={this.enterKeyEventHandler}/>
                    </Grid>
                    <Grid xs={1} md={1} item>
                        <Button fullWidth color="secondary" variant="outlined" onClick={this.onButtonClick}>
                            +
                        </Button>
                    </Grid>
               </Grid>
            </Paper>
        );
     }
}

export default AddTodo;

onKeyPress()는 키보드의 키가 누릴 때마다 실행되는 이벤트 핸들러다.

 

Todo 삭제

material-ui 컴포넌트 import

import {
     ListItem,
     ListItemText,
     InputBase,
     Checkbox,
     ListItemSecondaryAction,
     IconButton
} from "@material-ui/core";

import DeleteOutlined from "@material-ui/icons/DeleteOutlined"

 

Todo.js에서 삭제 버튼 추가

import React from "react";
import {ListItem, 
        ListItemText, 
        InputBase, 
        Checkbox, 
        ListItemSecondaryAction, 
        IconButton} from "@material-ui/core";
import DeleteOutlined from "@material-ui/icons/DeleteOutlined";       

class Todo extends React.Component {
    
    render() {
        const item = this.state.item;
        return(
            <ListItem>
               <Checkbox checked={item.done} disableRipple />
                <ListItemText>
                    <InputBase
                     inputProps={{"aria-label" : "naked"}
                     onClick={this.offReadOnlyMode}
                     type="text"
                     id={item.id}  //각 리스트를 구분하려고 id를 연결
                     name={item.id} //각 리스트를 구분하려고 id를 연결
                     value={item.title || ''}
                     multiline={true}
                     fullWidth={true}
                     onChange={this.editEventHandler}
                     onKeyPress={this.enterKeyEventHanlder}
                    />
               </ListItemText>

               <ListItemSecondaryAction>
                   <IconButton aria-label="Delete Todo" onClick={this.deleteEventHandler}>
                      <DeleteOutlined />
                   </IconButton>
               </ListItemSecondaryAction>
            </ListItem>
        );
    }
}

export default Todo;

 

App.js에서 delete() 함수 작성

    //삭제 함수
       delete = (item) => {
       const thisItem = this.state.items;
       console.log("Before Update Items : ", this.state.items)
       const newItems = thisItem.filter(e => e.id !== item.id);
       this.setState({items: newItems}, () => {
        
    // 디버깅 콜백
      console.log("Update Items : ", this.state.items);
         });
      }

 

App.js에서 Todo의 delete에 연결

//자바스크립트가 제공하는 map()을 이용해 배열을 반복해 <Todo /> 컴포넌트 생성
      const todoItems = this.state.items.length > 0 && 
         (
         <Paper style={{margin:16}}>
          <List>
            {this.state.items.map((item, idx) =>(
                <Todo item={item} key={item.id} delete={this.delete} />
            ))}
          </List>
         </Paper>
      )

 

Todo.js에 delete 함수 사용

constructor(props){
        ... 생략 
        this.delete = props.delete;

    }
    
    
 //삭제
deleteEventHandler = () => {
    this.delete(this.state.item);
}


<ListItemSecondaryAction>
       <IconButton aria-label="Delete Todo" onClick={this.deleteEventHandler}>
          <DeleteOutlined />
       </IconButton>
</ListItemSecondaryAction>

 

마무리

Todo리스트에 관한 서비스를 만드는 코드를 작성 했습니다. 수정관련된 코드는 생략 하겠습니다.

'개발 > 도서' 카테고리의 다른 글

TodoList 프론트엔드 서비스 개발 - 1  (0) 2022.08.25
React.js - 프론트엔드 개발  (0) 2022.08.18
Todo 서비스 구현(REST API)  (0) 2022.08.16
백엔드 서비스 아키텍처 - 2  (0) 2022.08.10
백엔드 서비스 아키텍처  (0) 2022.08.08