Redux는 단순히 글로벌 상태를 미화하지 않습니까?


84

그래서 일주일 전에 React를 배우기 시작했고 필연적으로 상태 문제와 컴포넌트가 나머지 앱과 통신하는 방식에 대해 알게되었습니다. 나는 주위를 수색했고 Redux는 이달의 풍미 인 것 같다. 나는 모든 문서를 읽었고 실제로 꽤 혁신적인 아이디어라고 생각합니다. 그것에 대한 내 생각은 다음과 같습니다.

상태는 일반적으로 프로그래밍에서 매우 사악하고 버그의 큰 원인으로 동의됩니다. 앱 전체에 분산시키는 대신 Redux는 변경하기 위해 작업을 내 보내야하는 전역 상태 트리에 모든 것을 집중시키는 것이 어떨까요? 흥미 롭 네요. 모든 프로그램에는 상태가 필요하므로 하나의 불순한 공간에 고정하고 버그를 추적하기 쉽도록 내부에서만 수정하십시오. 그런 다음 개별 상태 조각을 React 구성 요소에 선언적으로 바인딩하고 자동으로 다시 그리면 모든 것이 아름답습니다.

그러나이 전체 디자인에 대해 두 가지 질문이 있습니다. 우선 상태 트리가 변경 불가능해야하는 이유는 무엇입니까? 시간 여행 디버깅, 핫 리로드에 신경 쓰지 않고 이미 내 앱에서 실행 취소 / 다시 실행을 구현했다고 가정 해 보겠습니다. 이 작업을 수행하는 것이 너무 번거로운 것 같습니다.

case COMPLETE_TODO:
  return [
    ...state.slice(0, action.index),
    Object.assign({}, state[action.index], {
      completed: true
    }),
    ...state.slice(action.index + 1)
  ];

대신 :

case COMPLETE_TODO:
  state[action.index].completed = true;

말할 것도없이 내가 배우기 위해 온라인 화이트 보드를 만들고 있으며 모든 상태 변경은 명령 목록에 브러시 스트로크를 추가하는 것만 큼 간단 할 수 있습니다. 잠시 후 (수백 번의 브러시 스트로크)이 전체 어레이를 복제하면 비용과 시간이 많이 소요될 수 있습니다.

액션을 통해 변경되는 UI와는 독립적 인 전역 상태 트리는 괜찮지 만 실제로 변경 불가능해야합니까? 이와 같은 간단한 구현 (매우 대략적인 초안. 1 분 만에 작성)이 잘못된 것은 무엇입니까?

var store = { items: [] };

export function getState() {
  return store;
}

export function addTodo(text) {
  store.items.push({ "text": text, "completed", false});
}

export function completeTodo(index) {
  store.items[index].completed = true;
}

방출 된 작업을 통해 변경된 전역 상태 트리이지만 매우 간단하고 효율적입니다.


2
"첫째, 상태 트리가 변경 불가능해야하는 이유는 무엇입니까?" --- 그런 다음 데이터가 변경되었는지 확인하는 알고리즘을 제공해야합니다. 임의의 데이터 구조에 대해서는이를 구현할 수 없습니다 (변경 가능한 경우). 상용구를 줄이는 데 immutablejs사용 하십시오 return state.setIn([action.index, 'completed'], true);.
zerkms

1
추신 :return state.map(i => i.index == action.index ? {...i, completed: true} : i);
zerkms

답변:


52

Redux는 단순히 글로벌 상태를 미화하지 않습니까?

당연하지. 그러나 지금까지 사용한 모든 데이터베이스에 대해 동일하게 적용됩니다. Redux를 구성 요소가 반응 적으로 의존 할 수있는 인 메모리 데이터베이스로 취급하는 것이 좋습니다.

불변성은 하위 트리가 신원 확인까지 단순화되므로 매우 효율적으로 변경되었는지 확인할 수 있습니다.

예, 구현은 효율적이지만 트리가 어떻게 든 조작 될 때마다 전체 가상 DOM을 다시 렌더링해야합니다.

React를 사용하는 경우 결국 실제 dom과 비교하여 최소한의 배치 최적화 조작을 수행하지만 전체 하향식 다시 렌더링은 여전히 ​​비효율적입니다.

불변 트리의 경우 상태 비 저장 구성 요소는 종속 된 하위 트리가 이전 값과 비교하여 ID가 ​​다른지 확인하기 만하면됩니다. 그렇다면 렌더링을 완전히 피할 수 있습니다.


3
그래도 이것은 약간의 조기 최적화가 아닙니까? 또한, 우리가 어떻게 지속적으로 불변의 객체를 복제하는 비용보다 작은 것을 알고 다시 렌더링 DOM (도 반응하지 것의 가상 DOM 심하게이 비용을 완화?)
라이언 Peschel

3
글쎄, GUI 라이브러리는 이런 종류의 최적화를 오랫동안 (참조 : bitquabit.com/post/the-more-things-change ) 또한 불변 데이터 구조의 관리는 생각만큼 비용이 많이 들지 않습니다. 변경되면 부모의 단일 체인 만 연결하면됩니다. 나머지 노드는 영향을받지 않습니다. 따라서 모든 작업에 대해 전체 데이터 구조를 복제 하는 것이 아닙니다. 변경되지 않은 하위 구성 요소를 재사용하여 새로운 데이터 구조를 만듭니다.
lorefnon 2015 년

4
또한 Reacts Virtual DOM은 정확히 어두운 마법이 아닙니다. React 문서에서 인용 : "한 트리를 다른 트리로 변환하기 위해 최소 작업 수를 생성하는 것은 복잡하고 잘 연구 된 문제입니다.-최첨단 알고리즘은 순서가 복잡합니다. of O (n3) 여기서 n은 트리의 노드 수입니다. "
lorefnon

2
React가 실제로 훨씬 더 나은 성능을 발휘할 수있는 이유는 다음과 같습니다. React는 휴리스틱에 의존합니다. 따라서 : "안정적인 키를 제공하지 않으면 (예를 들어 Math.random () 사용) 모든 하위 트리가 사용자가 키를 선택할 수있는 선택권을 부여함으로써 사용자는 자신의 발을 쏠 수 있습니다. " 따라서 안정적인 키를 제공하여 React를 도울 수있는 것처럼, 변경 불가능한 데이터 소품을 제공하여 React를 도울 수있는 것과 같은 방식입니다.
lorefnon 2015 년

1
브러시 스트로크 배열에 관해서는 다음을 참조하십시오. facebook.github.io/immutable-js/docs/#/List Quoting from docs : Lists are ordered indexed density collections, like a JavaScript Array. 목록은 끝 (푸시, 팝) 및 시작 (언 시프트, 시프트) 모두에서 효율적으로 추가 및 제거하여 Deque를 구현합니다.
lorefnon 2015 년
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.