React 배열

데이터 추가

리액트에서는 this.state.array.push('some value'); 와 같이 state 내부의 값을 직접적으로 수정하면 절대 안됨!
이를 불변성 유지라고 하는데 push, splice, unshift, pop 같은 내장함수는 배열자체를 직접 수정하게 되므로 적합하지 않음
그 대신 기존의 배열에 기반하여 새 배열을 만들어내는 함수인 concat, slice, map, filter 같은 함수를 사용해야함
리액트에서 불변성 유지가 중요한 이유는 불변성을 유지해야, 리액트에서 모든것들이 필요한 상황에 리렌더링 되도록 설계할 수 있기 때문
그렇게 해야 나중에 성능도 최적화 할 수 있기 때문

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

  class App extends Component {
    id = 2
    state = {
      information: [
        {
          id: 0,
          name: '김민준',
          phone: '010-0000-0000'
        },
        {
          id: 1,
          name: '홍길동',
          phone: '010-0000-0001'
        }
      ]
    }
    handleCreate = (data) => {
      const { information } = this.state;
      this.setState({
        information: information.concat({ id: this.id++, ...data })
      })
    }
    render() {
      const { information } = this.state;
      return (
        <div>
          <PhoneForm
            onCreate={this.handleCreate}
          />
          {JSON.stringify(information)}
        </div>
      );
    }
  }

  export default App;
  • render함수에서 JSON.stringify를 활용해 information 값을 문자열로 변환

데이터 렌더링

  • 자바스크립트 배열의 내장함수인 map을 사용하여 위 배열을 컴포넌트로 변환해서 바꿔줌

map 함수 알아보기

1. forEach, push 함수 사용

  const a = [1,2,3,4,5];
  const b = [];

  b.forEach(number => b.push(number * 2));

2. map 함수 사용

  const a = [1,2,3,4,5];
  const b = a.map(number => number * 2);

컴포넌트 만들기

  import React, { Component } from 'react';

  class PhoneInfo extends Component {
    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;

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

  export default PhoneInfo;
  • info 라는 객체를 props 로 받아와서 렌더링, info 값을 전달하지 않게 된다면 컴포넌트가 크래쉬
  • info 가 undefined 일 때에는 비구조화 할당을 통해 내부의 값을 받아올 수 없기 때문
  • 그렇기 때문에 defaultProps를 통해 info의 기본값을 설정해줌
  import React, { Component } from 'react';
  import PhoneInfo from './PhoneInfo';

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

    render() {
      const { data } = this.props;
      const list = data.map(
        info => (<PhoneInfo key={info.id} info={info}/>)
      );

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

  export default PhoneInfoList;
  • 이 컴포넌트에서는 data 라는 배열을 가져와서 map 을 통하여 JSX 로 변환
  • key 는 리액트에서 배열을 렌더링을 할 때 꼭 필요한 값. 리액트는 배열을 렌더링 할 때 값을 통하여 업데이트 성능을 최적화

예시

  <div>A</div>
  <div>B</div>
  <div>C</div>
  <div>D</div>
  • 만약에 key 를 부여하지 않으면, 배열의 index 값이 자동으로 key 로 설정
  <div key={0}>A</div>
  <div key={1}>B</div>
  <div key={2}>C</div>
  <div key={3}>D</div>
  • 여기서 B와 C 사이에 X를 집어넣는다고 가정. key가 배열의 인덱스로 설정
  • 배열의 인덱스가 key 값으로 사용됨
  <div key={0}>A</div>
  <div key={1}>B</div>
  <div key={2}>X</div> [C -> X]
  <div key={3}>D -> C</div> [D -> C]
  <div key={4}>D</div> [새로 생성됨]
  • key를 배열의 index값으로 사용하는게 아니라, 우리가 데이터를 추가할 때마다 고정적인 고유 값을 부여해주면, 리액트가 변화를 감지해내고 업데이트를 할 때 효율적이게 처리
  <div key={0}>A</div>
  <div key={1}>B</div>
  <div key={5}>X</div> [새로 생성됨]
  <div key={2}>C</div> [유지됨]
  <div key={3}>D</div> [유지됨]
  • 결국 새로운 DOM은 하나만 생성되고 나머지는 그대로 유지됨
  • key는 고유값으로 설정

데이터 제거

  • 배열에서 3을 제거
  • slice와 concat 사용
  array.slice(0,2).concat(array.slice(3,5)) // [1, 2, 4, 5]
  • 전개연산자 사용하여 slice, concat 사용
  [ ...array.slice(0,2), ...array.slice(3,5) ];
  • filter 내장함수 사용
  array.filter(num => num !== 3); // [1, 2, 4, 5]

데이터 수정

  • 수정할때도 마찬가지로 불변성을 지켜야함. 기존의 배열과 그 내부에 있는 객체를 직접적으로 수정하면 안됨
  const array = [
    { id: 0, text: 'hello', tag: 'a' },
    { id: 1, text: 'world' , tag: 'b' },
    { id: 2, text: 'bye', tag: 'c' }
  ];
  const modifiedArray = array.map(item => item.id === 1
    ? ({ ...item, text: 'Korea' }) // id 가 일치하면 새 객체를 만들고, 기존의 내용을 집어넣고 원하는 값 덮어쓰기
    : item // 바꿀 필요 없는것들은 그냥 기존 값 사용

Categories:

Updated:

Comments