예제: mapStateToProps 함수

const mapStateToProps = state => {
 const { byIds, allIds } = state.todos || {};
 const todos =
   allIds && allIds.length
   ? allIds.map(id => ( byIds ? {...byIds[id], id}: null))
   : null;
    return { todos };
}

redux store에 있는 todos state를 가져오는 mapStateToProps 함수이다.

  • allIdsbyIds state는 아래와 같이 생겼다.
    allIds = [1,2,3];
    byIds = { 
      1: {content : '밥먹기', completed: true},
      2: {content : 'Redux 공부하기', completed: false},
      3: {content : '놀기', completed: true},
    };

    store에 있는 state를 가져오는건 알겠는데 todos를 만드는 부분에서 {...byIds[id], id} 이 부분이 이해가 잘 가지 않았다. 잘 쪼개서 살펴보자.

Step1. byIds[id]

byIds[1] = {content : '밥먹기', completed: true}
byIds[2] = {content : 'Redux 공부하기', completed: false}

Step 2 .{...byIds[id]}

... 를 이용하면 주어진 Object의 프로퍼티를 새로운 객체로 복사할 수 있다. 다만 spread 할 대상도 object이고 receiver 또한 객체여야 key-value 쌍이 복사된다.

let obj1 = { foo:'bar', x: 42 };
let obj2 = { foo:'baz', y: 13 };

let clonedObj = { ...obj1 }; 
// Object { foo:'bar', x: 42 }

즉 cloneObje라는 새로운 객체 { }에 obj1 내용을 복사하였다.

다시 돌아와서 {...byIds[id]}

  • spread 할 대상이 byIds[id] 객체이고, receiver 또한 { } 객체이기 때문에 { } 에 byIds[id]의 key-value 쌍들을 복사한다는 의미가 된다.

Step 3. {...byIds[id], id}

새로운 객체 { }에 byIds[id]의 내용을 복사했다. 마지막 id는 { id: 1 }도 추가해준다는 의미이다.

  • ES6 부터는 객체의 프로퍼티의 이름과 로컬 변수의 이름이 같으면 객체의 속성을 표시해주지 않고 하나만 나타낸다.
    즉, ES5에서는 { id : id } 이렇게 나타내야했던 반면 ES6에서는 { id } 로 간단하게 나타낼 수 있다.
{...byIds[id], id }; 
{ content : '밥먹기', completed: true, id: 1 } 

즉 다시 코드를 살펴보면

const mapStateToProps = state => {
 const { byIds, allIds } = state.todos || {};
 const todos =
   allIds && allIds.length
   ? allIds.map(id => ( byIds ? {...byIds[id], id}: null)) // 1.
   : null;
    return { todos }; // 2.
}
  1. todos에 저장된 id 순서로 [{content: 'blabla', completed: false, id: 1}, {content: 'blahblah', completed: false, id: 2}] 배열을 만들고
  2. 이를 다시 새로운 객체에 todos라는 name으로 넣어준다.