ABOUT ME

chanho Yoon
chyoon0512@gmail.com


깃허브


블로그 이사!

이 블로그로 이사했어요!!


Today
-
Yesterday
-
Total
-
  • React 할 일 목록 만들기 ( TodoList ) 추가,수정,삭제,검색
    Programming/React 2020. 11. 22. 23:52
    반응형

    실습은 npx react-creat-app [projectname] 으로 실습환경 구축

    기능은 추가, 수정, 삭제, 검색을 만들도록 하겠습니다.

    프로젝트 구조

    실습코드

    app.js

    import React, { Component } from 'react';
    import ToDoForm from './component/ToDoForm';
    import ToDoList from './component/ToDoList';
    import './App.css';
    class App extends Component {
      id = 4;
      state = {
        toDoList: [
          {
            id: 1,
            text: '러닝 뛰기',
          },
          {
            id: 2,
            text: '공부하기',
          },
          {
            id: 3,
            text: '독서하기',
          },
        ],
        search: '',
      };
    
      handleCreate = () => {};
      handleUpdate = (id, data) => {};
      handleRemove = (id) => {};
      render() {
        const { toDoList } = this.state;
        return (
          <div>
            <ToDoForm onCreate={this.handleCreate} />
            <ToDoList data={toDoList} onUpdate={this.handleUpdate} onRemove={this.handleRemove} />
          </div>
        );
      }
    }
    
    export default App;
    

    ToDoForm 컴포넌트는 할일 목록을 입력받아 toDoList 배열에 추가할 props handleCreate를 전달한다.

    ToDoList는 할일 목록을 출력해주는 컴포넌트로 props로 toDoList, handleUpdate, handleRemove 를 컴포넌트에 전달한다.


    우선 ToDoList 컴포넌트를 작성하여 미리 작성된 배열 오브젝트들을 보여주도록 하겠습니다.

     

    ToDoList.js

    import React, { Component } from 'react';
    import ToDoInfo from './ToDoInfo';
    
    class ToDoList extends Component {
      state = {
        style: {
          border: '1px solid black',
          padding: '25px',
          margin: '15px',
        },
      };
      render() {
        const { data, onUpdate, onRemove } = this.props;
    
        return (
          <div>
            <ul>
              {data.map((data) => (
                <li style={this.state.style}>
                  <ToDoInfo data={data} onUpdate={onUpdate} onRemove={onRemove} />
                </li>
              ))}
            </ul>
          </div>
        );
      }
    }
    
    export default ToDoList;
    

    props로 전달받은 data를 가져와 map 메소드를 사용하여 li를 출력해주도록 합니다.

    여기서 li에 ToDoInfo 컴포넌트를 해준 이유는 map으로 각각의 배열을 출력할 때 해당하는 정보를 ToDoInfo 컴포넌트로 전달하여 보여주기 위함입니다. 


    ToDoInfo.js

    import React, { Component } from 'react';
    
    class ToDoInfo extends Component {
      render() {
        const { data, onUpdate, onRemove } = this.props;
        return (
          <div>
            <span>{data.text}</span>
          </div>
        );
      }
    }
    
    export default ToDoInfo;
    

    여기까지 작성했다면 아래와 같이 결과가 출력될 것 입니다.

    이제 여기서 각각의 ToDoInfo에 수정과 삭제를 위해 버튼을 하나 생성하고 거기에 맞는 핸들 메소드를 작성하도록 하겠습니다.

     

    수정

    import React, { Component } from 'react';
    
    class ToDoInfo extends Component {
      state = {
        toggle: false,
        text  : '',
        style : {
          margin: '10px',
        },
      };
    
      handleChange = ( e ) => {
        this.setState({
          [e.target.name]: e.target.value,
        });
      };
      handleToggleChange = () => {
        const { toggle, text } = this.state;
        const { data, onUpdate } = this.props;
        // false -> true
        if (!toggle) {
          this.setState({
            text  : data.text,
            toggle: true,
          });
        } else {
          onUpdate(data.id, { text: text });
          this.setState({
            toggle: false,
          });
        }
        // ture -> false
      };
    
      handleRemove = () => {};
    
      render() {
        const { data } = this.props;
        const { toggle, text } = this.state;
        console.log(data.text + ' 렌더링 됐어유');
        return (
          <div>
            {toggle ? (
              <input
                style={this.state.style}
                onChange={this.handleChange}
                value={text}
                name="text"
              ></input>
            ) : (
              <span style={this.state.style}>{data.text}</span>
            )}
            <button onClick={this.handleToggleChange}>{toggle ? '적용' : '수정'}</button>
            <button onClick={this.handleRemove}>삭제</button>
          </div>
        );
      }
    }
    
    export default ToDoInfo;
    

    toggle 을 만들어 false와 true일 때 handleToggleChange 메소드를 이용하여 각각에 맞는 이벤트들을 처리하도록 했습니다.

    handleToggleChange() 메소드에서는 필요한게 두 가지 입니다.

    toggle이 false -> true 일 때와 ture -> false일 때 입니다. 

    false -> ture  :  수정 버튼을 눌렀을 경우 input 창 value에 기존에 입력되었던 data.text값을 가져온다

    toggle false -> true

    ture => false : 적용 버튼을 누른 경우로 업데이트를 위해 App.js 컴포넌트의 handleUpdate로 보낸다

    // App.js 에서의 handleUpdate 부분
    handleUpdate = (id, data) => {
        console.log(id);
        console.log(data);
      };

    이렇게 바뀐 값들이 handleUpdate 로 넘오오게 된다.

    App.js / handleUpdate 부분

      handleUpdate = (id, data) => {
        const { toDoList } = this.state;
    
        this.setState({
          toDoList: toDoList.map((toDoList) => {
            console.log(toDoList);
            if (toDoList.id === id) {
              console.log(toDoList.id + ' / ' + id);
              return {
                id,
                ...data,
              };
            }
            return toDoList;
          }),
        });
      };

    map  메소드를 사용하여 id값이 서로 같은 경우 수정하려는 배열이 맞으므로 거기만 새로 받아온 data 를 반환해준다.

     

    삭제

    ToDoInfo.js / handleRemove 부분

    handleRemove = () => {
      const { data, onRemove } = this.props;
      onRemove(data.id);
    };

    App.js / handleRemove 부분

      handleRemove = (id) => {
        const { toDoList } = this.state;
    
        this.setState({
          toDoList: toDoList.filter((data) => data.id !== id),
        });
      };

    삭제는 비교적 간단합니다. id값을 가져와 filter 메소드로 받아온 id값과 틀린 것만 toDoList에 반환시키고 id값이 같을 경우 반환시키지 않으면 됩니다.

     

    추가

    ToDoForm.js

    import React, { Component } from 'react';
    
    class ToDoForm extends Component {
      state = {
        text: '',
      };
      handleChange = (e) => {
        this.setState({
          [e.target.name]: e.target.value,
        });
      };
      handleSubmit = (e) => {
        e.preventDefault();
        this.props.onCreate(this.state);
        this.setState({
          text: '',
        });
      };
      render() {
        const { text } = this.state;
        return (
          <div>
            <form onSubmit={this.handleSubmit}>
              <input value={text} name="text" placeholder="..입력" onChange={this.handleChange}></input>
              <button type="submit">추가</button>
            </form>
          </div>
        );
      }
    }
    
    export default ToDoForm;
    

    input onChange이벤트로 입력받은 값을 state 에 저장하고 submit 이벤트 발생시 handleSubmit에서는 this.props.onCreate(this.state)로 현재의 state 값을 부모 컴포넌트로 값을 보낸다.

     

    App.js / handleCreate 부분

      handleCreate = (data) => {
        console.log(data);
      };

    리스트에 추가하려는 데이터가 console창에서 확인결과 잘 받아오고 있다.

    이제 받아온 값을 기존의 toDoList 배열에 추가만 해주면 된다.

      handleCreate = (data) => {
        const { toDoList } = this.state;
    
        this.setState({
          toDoList: toDoList.concat({
            id: this.id++,
            ...data,
          }),
        });
      };

    concat을 사용하여 기존에 있던 toDoList배열에 추가하면 끝입니다.

     

    검색

    검색은 간단히 indexOf을 사용하여 ToDoList에 해당하는 값만 전달하여 검색하는 방식으로 하면 간단하게 구현할 수 있습니다.

     

    App.js / handleSearch 부분

      handleSearch = (e) => {
        this.setState({
          [e.target.name]: e.target.value,
        });
      };

    App.js / render 부분

      render() {
        const { toDoList, search } = this.state;
        return (
          <div>
            <ToDoForm onCreate={this.handleCreate} />
            <input value={search} name="search" onChange={this.handleSearch} placeholder=" ..검색" />
            <ToDoList
              data={toDoList.filter((data) => data.text.indexOf(search) !== -1)}
              onUpdate={this.handleUpdate}
              onRemove={this.handleRemove}
            />
          </div>
        );
      }

    input에 onChange 를 사용해서 state에 있는 search 값을 저장해주도록했습니다.

    그리고 ToDoList 컴포넌트에 data props를 전달해 줄 때 filter 메소드를 사용하여 text에 검색하려는 단어가 있을 경우에만 배열을 반환하여 ToDoList 컴포넌트에 전달하도록 했습니다.

     


     

    댓글

Designed by Tistory.