2014-10-03 3 views
2

이 예제는 다소 고안되었지만 나와 함께합니다. , 마지막 LINEITEM 선택된 상태 내 구성 요소의 상태를 변경 한 것으로 보인다 (사실 순서) OrderApp.setOrderSelected를 호출의 완료시여러 순차적 상태 업데이트의 올바른 처리

var OrderApp = React.createClass({ 
    getInitialState: function() { 
     return { 
      selectedOrders: {}, 
      selectedLineItems: {} 
     }; 
    }, 

    setOrderSelected: function(order, newSelectedState) { 
     var mutation = {}; 
     mutation[order.id] = {$set: newSelectedState}; 
     var newSelectedOrders = React.addons(this.state.selectedOrders, mutation); 
     _.each(order.lineItems, function(lineItem) { 
      setLineItemSelected(lineItem, newSelectedState); 
     }); 
     this.setState({selectedOrders: newSelectedOrders}); 
    }, 

    setLineItemSelected: function(lineItem, newSelectedState) { 
     var mutation = {}; 
     mutation[lineItem.id] = {$set: newSelectedState}; 
     var newSelectedLineItems = React.addons(this.state.selectedLineItems, mutation); 
     this.setState({seelctedLineItems: newSelectedLineItems}); 
    } 
}); 

: 나는 반작용 구성 요소의 일원으로 두 가지 기능을 말해봐. 내가 setState를에 대한 호출을 일괄 처리되는 반작용 때문입니다 추측하고있어, 그래서 내가 전화있을 때 : 두 번째 기능에

var newSelectedLineItems = React.addons(this.state.selectedLineItems, mutation); 

, 나는 원래 상태로 각 시간을 따기하고있어 그렇게 만 마지막 돌연변이가 발생합니다.

부모 함수에서 모든 상태 변이를 수집하고 setState를 한 번만 호출해야합니까? 이것은 나에게 조금 clunky 느낌, 그리고 만약 내가 간단한 솔루션을 놓치고 궁금하네요.

답변

2

구성 요소 내에서 지정된 실행 스레드에서 this.setState을 두 번 이상 호출하면 안됩니다. 직접 상태를 수정하고 완료 후 this.forceUpdate을 사용할 수 있습니다 -

사용 forceUpdate 대신 setState를이

당신은 this.setState를 사용할 필요가 없습니다 : 그래서

당신은 몇 가지 옵션을 가지고 .

여기서 중요한 점은 직접 수정을 시작하자 마자 this.state을 오염 된 것으로 간주해야한다는 점입니다. IE : this.forceUpdate을 호출 할 때까지 수정 한 상태 또는 속성을 사용하지 마십시오. 이것은 일반적으로 문제가되지 않습니다.

this.state 내에 중첩 된 객체를 처리 할 때이 방법이 절대적으로 좋습니다. 개인적으로 나는 문법이 매우 까다 롭기 때문에 React.addons.update의 거대한 팬이 아닙니다. 나는 직접적으로 그리고 forceUpdate을 수정하는 것을 선호한다.

는 실행 스레드의 말에 this.setState에 전달 수집, 모든 변화의 객체를 마침내 setState를

에서 사용 할 때까지 주변에 통과 개체를 만듭니다.

1

불행히도 얕은 병합에는 문제가 있습니다. 업데이트를 수집하고 한 번에 적용해야합니다.

이 당신이 믹스 인을 사용해야 정말 좋은 징조 나

에 투박한 조금 느낌! 이 코드는 꽤 끔찍한 것처럼 보일 뿐이지 만, 사용하면 꽤 멋지다 고 할 수 있습니다.

var React = require('react/addons'); 
var UpdatesMixin = { 
    componentDidMount: function(){ 
     this.__updates_list = []; 
    }, 
    addUpdate: function(update){ 
     this.__updates_list.push(update); 
     if (this.__updates_list.length === 1) { 
     process.nextTick(function(){ 
      if (!this.isMounted()) { 
      this.__updates_list = null; 
      return; 
      } 

      var state = this.__updates_list.reduce(function(state, update){ 
      return React.addons.update(state, update); 
      }, this.state); 

      this.setState(state); 
      this.__updates_list = [];  
     }.bind(this)); 
     } 
    } 
}; 

requirebin

그것은 setState를을 수행 한 후, 동 기적으로 발생하는 모든 업데이트를 버퍼링 this.state 그들을 적용합니다.

사용법은 다음과 같습니다 (전체 데모는 requirebin을 참조하십시오).

this.addUpdate({a: {b: {$set: 'foo'}}; 
this.addUpdate({a: {c: {$set: 'bar'}}; 

은 (예를 들어, 업데이트 객체를 병합하여)을 최적화 할 수있는 몇 가지 장소가있다, 그러나 당신은 당신의 구성 요소를 변경하지 않고 나중에 할 수 있습니다.

+0

React에 새로운 브랜드이기 때문에 여기에서는 Mixin을 사용하지 않을 것이라고 생각했지만, 분명히 훨씬 더 깨끗해졌습니다. 내 질문 하나 귀하의 솔루션 process.nextTick에 대한 호출이 포함됩니다. 찾을 수있는 유일한 문서는 이것이 노드 특정 라이브러리임을 제안합니다. 클라이언트에서 처리 할 때 업데이트를 버퍼링하는 데 사용할 수있는 유사한 라이브러리가 있습니까? – tnorwood

+0

browserify/webpack을 사용하지 않는 경우 독립형 shim을 다운로드 할 수 있습니다. http://wzrd.in/standalone/process%2fbrowser - 대부분의 사람들은 cjs 모듈을 사용하므로 직접 라이브러리를 컴파일해야합니다. npm은 종종 유일한 배포 매체입니다. – FakeRainBrigand

+0

내 질문에 대한 답변이 정말 마음에 들었습니다. 마이크의 대답은 외부 의존성이 필요 없기 때문에 받아 들여지는 것으로 표시했습니다. 나는 당신의 대답이 더 많은 ReactJS 사고에서 문제에 접근 할 수있는 강력한 사례가 있다고 생각합니다. 도와 주셔서 감사합니다. – tnorwood