본문 바로가기
프로그래밍 개발/ReactJs

ReactJs - 배열을 다루는 CRUD 구현

by Jinseok Kim 2021. 1. 7.
반응형

 

 

배열을 다루는 CRUD 구현

 

 

생성과 렌더링

 

  • 리액트애서는 state 내부의 값을 직접적으로 수정하면 절대로 안된다.
  • 이를 불변성 유지라고 하는데, push, splice, unshift, pop 같은 내장함수는 배열 자체를 직접 수정하게 되므로 적합하지 않는다.
  • 그 대신에, 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용하면된다.

 

App.js

import React, { Component } from 'react';
import PhoneForm from "./components/PhoneForm";
import './App.css';

class App extends Component {
id =2 
state = {
    information:[
        {
            id: 0,
            name: '김진석',
            phone: '010-0000-0000'
        },
        {
          id: 1,
            name: '김진석2',
            phone: '010-0000-0000'  
        }
    ]
}
handleCreate = (data)=>{
    const {information} = this.state;
    this.setState({
        information: information.concat({ id: this.id++, ...data }) //concat을 이용하여 배열을 조절
    })                                                              //여기서 id 값은 각 데이터를 식별하기 위함이다.
    
}
 render() {
    const { information } = this.state;
    return (
      <div>
        <PhoneForm
          onCreate={this.handleCreate}
        />
         <PhoneInfoList data={this.state.information}/>
      </div>
    );
  }
}
export default App;

 

 

 

PhoneForm.js

import React, { Component } from 'react';

class PhoneForm extends Component {
  state = {
    name: '',
    phone: ''
  }
  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    })
  }
  handleSubmit = (e) => {
    
    e.preventDefault();
    
    this.props.onCreate(this.state);
    
    //submit이 끝나면 다시 폼 값을 초기화 시킨다.
    this.setState({
      name: '',
      phone: ''
    })
  }
  render() {
    return (
      <form onSubmit={this.handleSubmit}> //submit 버튼 누르면 반응하여 부모인 App.js로 폼 값 전달
        <input
          placeholder="이름"
          value={this.state.name}
          onChange={this.handleChange} //폼 값 수정시 반응
          name="name"
        />
        <input
          placeholder="전화번호"
          value={this.state.phone}
          onChange={this.handleChange}  //폼 값 수정시 반응
          name="phone"
        />
        <button type="submit">등록</button> //submiit 버튼 추가
      </form>
    );
  }
}

export default PhoneForm;

 

 

 

 

 

 

 

 

데이터 랜더링

 

 

PhoneInfo.js

각 전화번호 정보를 보여주는 컴포넌트다.

import React, { Component } from 'react';

class PhoneInfo extends Component {
// info 가 undefined 일 때에는 비구조화 할당을 통해 내부의 값을 받아올 수 없기 때문에
//defaultProps 를 통하여 info 의 기본값을 설정해주었다.
  static defaultProps = {
    info: {
      name: '이름',
      phone: '010-0000-0000',
      id: 0
    }
  }

  render() {
    const style = {
      border: '1px solid black',
      padding: '8px',
      margin: '8px'
    };

    const {
      name, phone, id
    } = this.props.info; //부모인 PhoneInfoList에서 props을 이용해 name, phone, id 값 가져옴

    return (
      <div style={style}>
        <div><b>{name}</b></div>
        <div>{phone}</div>
      </div>
    );
  }
}

export default PhoneInfo;

 

 

 

PhoneInfoList.js

여러개의 PhoneInfo 컴포넌트들을 보여준다.

import React, { Component } from 'react';
import PhoneInfo from './PhoneInfo';


class PhoneInfoList extends Component {

static defaultProps = {
    data: []
  }

  render() {
    const { data } = this.props; //부모인 App.js에서 props을 이용해 data 값 가져옴
    const list = data.map( //map 메소드를 이용하여 조건대로 배열 list을 새롭게 배열화시킨다.
      info => (<PhoneInfo key={info.id} info={info}/>) //자식인 PhoneInfo로 props기능으로 전달
    );

    return (
      <div>
        {list}    
      </div>
    );
  }
}

export default PhoneInfoList;

 

  • data 라는 배열을 가져와서 map 을 통하여 JSX 로 변환을 해준다.
  • 이 과정에서, key 라는 값도 설정이 되었는데, 여기서 key 는 리액트에서 배열을 렌더링을 할 때 꼭 필요한 값이다. 

 

 

 

 

 

 

 

 

데이터 제거

 

App.js

 

import React, { Component } from 'react';
import PhoneForm from "./components/PhoneForm";
import './App.css';
import PhoneInfoList from "./components/PhoneInfoList";


class App extends Component {
id =2 
state = {
    information:[
        {
            id: 0,
            name: '김진석',
            phone: '010-0000-0000'
        },
        {
          id: 1,
            name: '김진석2',
            phone: '010-0000-0000'  
        }
    ]
}
handleCreate = (data)=>{
    const {information} = this.state;
    this.setState({
        information: information.concat({ id: this.id++, ...data })
    })
    
}
handleRemove = (id) => {
    const { information } = this.state;
    this.setState({
      information: information.filter(info => info.id !== id)
    })
  }

 render() {
    const { information } = this.state;
    return (
      <div>
        <PhoneForm
          onCreate={this.handleCreate}
        />

 //id 를 파라미터로 받아오는 handleRemove 라는 함수를 만들어,porps로 PhoneInfoList 로 전달
        <PhoneInfoList data={this.state.information}
         onRemove={this.handleRemove} 
        
        />
        
      </div>
    );
  }
}
export default App;

 

 

 

PhoneInfoList.js

import React, { Component } from 'react';
import PhoneInfo from './PhoneInfo';

class PhoneInfoList extends Component {
  static defaultProps = {
    data: []
  }

//PhoneInfoList 에서는 props 로 전달받은 onRemove 를 그대로 다시 자식인 PhoneInfo로 전달한다.
  render() {
    const { data, onRemove } = this.props;
    const list = data.map(
      info => (<PhoneInfo key={info.id} info={info}  onRemove={onRemove}/>)
    );

    return (
      <div>
        {list}    
      </div>
    );
  }
}

export default PhoneInfoList;

 

 

PhoneInfo.js

import React, { Component } from 'react';

class PhoneInfo extends Component {
  static defaultProps = {
    info: {
      name: '이름',
      phone: '010-0000-0000',
      id: 0
    }
  }
 handleRemove = () => {
    // 삭제 버튼이 클릭되면 onRemove 에 id 넣어서 호출
    const { info, onRemove } = this.props;
    onRemove(info.id);
  }

  render() {
    const style = {
      border: '1px solid black',
      padding: '8px',
      margin: '8px'
    };

    const {
      name, phone, id
    } = this.props.info;

    return (
      <div style={style}>
        <div><b>{name}</b></div>
        <div>{phone}</div>
        <button onClick={this.handleRemove}>삭제</button>
      </div>
    );
  }
}

export default PhoneInfo;

 

 

 

 

 

 

 

 

데이터 수정

 

 

App.js

 

import React, { Component } from 'react';
import PhoneForm from "./components/PhoneForm";
import './App.css';
import PhoneInfoList from "./components/PhoneInfoList";


class App extends Component {
id =2 
state = {
    information:[
        {
            id: 0,
            name: '김진석',
            phone: '010-0000-0000'
        },
        {
          id: 1,
            name: '김진석2',
            phone: '010-0000-0000'  
        }
    ]
}
handleCreate = (data)=>{
    const {information} = this.state;
    this.setState({
        information: information.concat({ id: this.id++, ...data })
    })
    
}
handleRemove = (id) => {
    const { information } = this.state;
    this.setState({
      information: information.filter(info => info.id !== id)
    })
  }
handleUpdate = (id, data) =>{
    const {information} = this.state;
    this.setState({
        information: information.map(info => id === info.id ? { ...info, ...data }
        // 새 객체를 만들어서 기존의 값과 전달받은 data 을 덮어씀
        : info // 기존의 값을 그대로 유지
        )
        
    })
    
}

 render() {
    const { information } = this.state;
    return (
      <div>
        <PhoneForm
          onCreate={this.handleCreate}
        />
        
        <PhoneInfoList data={this.state.information}
         onRemove={this.handleRemove}
         onUpdate={this.handleUpdate}
        />
        
        
      </div>
    );
  }
}
export default App;

 

 

 

PhoneInfoList.js

import React, { Component } from 'react';
import PhoneInfo from './PhoneInfo';

class PhoneInfoList extends Component {
  static defaultProps = {
    data: []
  }

  render() {
    const { data, onRemove, onUpdate } = this.props; //porps으로 부모에게 받아 onUpdate추가
    const list = data.map(
      info => (<PhoneInfo 
       key={info.id}
       info={info}  
       onRemove={onRemove}
       onUpdate={onUpdate}/>) //porps으로 다시 하위 자식으로 전달
    );

    return (
      <div>
        {list}    
      </div>
    );
  }
}

export default PhoneInfoList;

 

 

 

 

 

PhoneInfo.js

import React, { Component } from 'react';

class PhoneInfo extends Component {
  static defaultProps = {
    info: {
      name: '이름',
      phone: '010-0000-0000',
      id: 0
    }
  }
state = {
    editing: false,
    name: '',
    phone: '',
}
 handleRemove = () => {
    // 삭제 버튼이 클릭되면 onRemove 에 id 넣어서 호출
    const { info, onRemove } = this.props;
    onRemove(info.id);
  }
   // editing 값을 반전시키는 함수
  // true -> false, false -> true
 handleToggleEdit= ()=>{
     const{editing} =this.state;
     this.setState({
         editing: !editing
     });
    
 }
 
  // input 에서 onChange 이벤트가 발생 될 때
  // 호출되는 함수
 handleChange=(e)=>{
     const{name, value}= e.target;
     this.setState({
         [name]: value
     });
 }
  componentDidUpdate(prevProps, prevState){
  // 여기서는 editing 값이 바뀔 때 처리 할 로직이 존재한다.
    // 수정을 눌렀을땐, 기존의 값이 input에 나타나고,
    // 수정을 적용할땐, input 의 값들을 부모한테 전달해준다.
       const { info, onUpdate } = this.props;
    if(!prevState.editing && this.state.editing) {
      // editing 값이 false -> true 로 전환 될 때
      // info 의 값을 state 에 넣어준다
      this.setState({
        name: info.name,
        phone: info.phone
      })
    }

    if (prevState.editing && !this.state.editing) {
      // editing 값이 true -> false 로 전환 될 때
      onUpdate(info.id, {
        name: this.state.name,
        phone: this.state.phone
      });
    }
      
  }

  render() {
    const style = {
      border: '1px solid black',
      padding: '8px',
      margin: '8px'
    };
      const {editing} = this.state;
      
      
      if(editing){ //수정모드
            return (
      <div style={style}>
        <div>
            <input
              value={this.state.name}
              name="name"
              placeholder="이름"
              onChange={this.handleChange}
            />
          </div>
          <div>
            <input
              value={this.state.phone}
              name="phone"
              placeholder="전화번호"
              onChange={this.handleChange}
            />
          </div>
         <button onClick={this.handleToggleEdit}>적용</button>        
        <button onClick={this.handleRemove}>삭제</button>
      </div>
    );
      }
        
//일반모드
    const { 
      name, phone
    } = this.props.info;

    return (
      <div style={style}>
        <div><b>{name}</b></div>
        <div>{phone}</div>
         <button onClick={this.handleToggleEdit}>수정</button>
        <button onClick={this.handleRemove}>삭제</button>
      </div>
    );
  }
}

export default PhoneInfo;

 

 

 

 

 

반응형

'프로그래밍 개발 > ReactJs' 카테고리의 다른 글

ReactJs - input  (0) 2021.01.06
ReactJs - LifeCycle API  (0) 2021.01.06
ReactJs - props 와 state  (0) 2021.01.05
ReactJs - JSX 기본  (0) 2021.01.05
ReactJs - Update , Delete기능 구현하기  (0) 2021.01.04

댓글