2017-09-14 13 views
0

요구 사항는 것입니다 :은 관찰자의 구성 요소가 업데이트 후 렌더링 호출되지 않은 반응 mobx

토글 시안의 배경색으로 행 구성 요소를

강조 선택한 행을 열

그러나 토글 버튼을 클릭하면 App 구성 요소가 다시 렌더링되지 않습니다. (

// App.js 
import React, { Component } from 'react'; 
import {observable, action } from 'mobx'; 
import {observer} from 'mobx-react'; 

@observer class Rows extends Component { 
    rows() { 
    let { store } = this.props; 
    var rows = []; 
    for (var i = 4; i > 0; i--) { 
     rows.push(
     <div 
      style={i == store.selectedRow ? { backgroundColor: "cyan" } : null } 
      onClick={store.selectRow.bind(this, i)}> 
      { i } 
     </div> 
    ) 
    } 
    return rows; 
    } 
    render() { 
    return (<div>{this.rows()}</div>); 
    } 
} 

class Store { 
    constructor(props) { 
    this.selectRow = this.selectRow.bind(this) 
    this.toggleSelector = this.toggleSelector.bind(this) 
    } 
    @observable showSelector = false; 
    @observable selectedRow = 4; 
    @action selectRow(n) { 
    this.selectedVersion = n; 
    } 
    @action toggleSelector() { 
    this.showSelector = !this.showSelector; 
    } 
} 

//edit here 
const store = new Store(); 

@observer class App extends Component { 
    render() { 
    return (
     <div className="App"> 
     <button onClick={store.toggleSelector}>Toggle Selector</button> 
     { store.showSelector ? <Rows store={store}/> : null } 
     </div> 
    ); 
    } 
} 

export default App; 

EDIT 제안에 따라 구성 요소 외부에서 저장소를 추출했습니다.

+0

App의 렌더링에 새'store '를 만들지 마십시오. 대신 클래스 외부에서 생성하십시오. – Tholle

+0

아무 것도 변경하지 않습니다. 그래도 제안에 감사드립니다. –

답변

1

업데이트 : @action.bound 데코레이터를 사용하고 생성자에서 bind(this)을 모두 건너 뛸 수 있습니다. 내 생각 엔 수동 바인딩이 바인딩을 엉망으로 만드는 것입니다.

는 액션 장식/기능은 자바 스크립트 바인딩에 대한 일반적인 규칙을 다음과 action.bound

참조하십시오. 그러나 Mobx 3에서는 action.bound를 도입하여 작업을 대상 객체에 자동 바인딩합니다. action과 달리 action.bound는 name 매개 변수를 사용하지 않으므로 이름은 항상 작업이 바인딩 된 속성 이름을 기반으로합니다. 이render() 내부 을 만들어 있기 때문에


귀하의 상점은 관찰되지 않습니다. 저장소를 만들고 props 또는 MobX의 Provider을 통해 저장소로 전달해야합니다.

공급자는 React의 컨텍스트 메커니즘을 사용하여 하위 구성 요소에 상점 (또는 다른 것들)을 전달할 수있는 구성 요소입니다. 이는 구성 요소의 여러 계층을 명시 적으로 통과시키지 않으려는 경우 유용합니다.

주사를 사용하여 해당 상점을 선택할 수 있습니다. 문자열 목록을 사용하여 래핑 된 구성 요소에서 해당 상점을 사용할 수있게하는 상위 구성 요소입니다.

+0

구성 요소 외부에서 파일을 정의해도 내 출력은 변경되지 않습니다. 생각해 줘서 고마워. 공급자를 시도 할 것입니다. –

+0

이 솔루션의 경우 공급자가 과잉이라고 생각됩니다. 내 실제 프로젝트에서 도움이 될 것입니다. 감사합니다. –

+0

구성 요소의 내부 상태 (다른 구성 요소와 공유되지 않는 상태)를 관리하는 데 관심이 있다면 간단히 'Component.setState'를 사용할 수 있습니다. –

0

시도해보십시오.

// App.js 
import React, { Component } from 'react'; 
import {observable, action } from 'mobx'; 
import {observer} from 'mobx-react'; 

@observer class Rows extends Component { 
    rows() { 
    let { store } = this.props; 
    var rows = []; 
    for (var i = 4; i > 0; i--) { 
     rows.push(
     <div 
      style={i == store.selectedRow ? { backgroundColor: "cyan" } : null } 
      onClick={store.selectRow.bind(this, i)}> 
      { i } 
     </div> 
    ) 
    } 
    return rows; 
    } 
    render() { 
    return (<div>{this.rows()}</div>); 
    } 
} 

class Store { 
    constructor(props) { 
    this.selectRow = this.selectRow.bind(this) 
    this.toggleSelector = this.toggleSelector.bind(this) 
    } 
    @observable showSelector = false; 
    @observable selectedRow = 4; 
    @action selectRow(n) { 
    this.selectedVersion = n; 
    } 
    @action toggleSelector() { 
    this.toggleSelector = !this.showSelector; 
    } 
} 

// defined outside 
const store = new Store(); 

@observer class App extends Component { 
    render() { 
    return (
     <div className="App"> 
     <button onClick={store.toggleSelector}>Toggle Selector</button> 
     { store.showSelector ? <Rows store={store}/> : null } 
     </div> 
    ); 
    } 
} 

export default App; 
+0

아니요. 심지어 그것을 밖으로 파일을 정의하는 내 출력 변경하지 않습니다. . –