2017-01-26 10 views
1

observable.map()のマップ/トランスフォームを作成するにはどうすればよいですか?例えばMobXマップマップ

Iは、それらid sはキーであると、Todosobservable.map()を持っている場合:

var Todos = observable.map({ 
    'rf8r4': {id: 'rf8r4', description: 'Get milk'}, 
    '543w4': {id: '543w4', description: 'Code in MobX'}, 
    '099i0': {id: '099i0', description: 'Sleep'} 
}) 

どのように自動的にtrue(をデフォルトvisibleプロパティを含む例えばように、UI状態observable.map()を生成することができます

ui_state = observable.map({ 
    'rf8r4': {visible: true}, // defaults 
    '543w4': {visible: false}, // changed to false after some user interaction 
    '099i0': {visible: true} 
}) 

が、必ず各藤堂のSTことを行います。)キーは上記Todosのものに対応気づきます(visibleプロパティがまだfalseあるか543w4年代に気づく)

Todos.set('grtg6', {id: 'grtg6', description: 'Read StackOverflow'}) 

になる必要があります。次のようなオリジナルTodosマップへの変更は、後に一貫性のある滞在を食べた

ui_state = observable.map({ 
    'rf8r4': {visible: true}, 
    '543w4': {visible: false}, 
    '099i0': {visible: true}, 
    'grtg6': {visible: true} // this is the new one 
}) 

私は、autorun/createTransformerを試してみましたそれは副作用のように最後に更新されますので、ui_stateをReactコンポーネントに使用することはできません。

は、私はまた、computedの異なるバージョンを試してみましたが、それは、新しいui_stateたびに作成し、私はcomputed関数内createTransformerを使用している場合、私はエラーが出るので...

ありがとう!

答えて

0

実際には、常に更新されたmapのマップを作成する最良の方法を見つけました。 MobX Documentation on createTransformerを参照してください。

私はcreateTransformerを試して問題を起こしていたという質問に言及しました。これは、autorunが副作用を実行するためのものであるため、すべてのMobXデータが更新された後に実行されるためです。つまり、mapmapのマップの両方に依存するMobXデータ(「X」など)がある場合は、mapが更新されると「X」が更新されますが、Xの他の依存関係、マップのマップ、autorunがまだ実行されておらず、結果として得られる 'X'の値が間違っているか、計算自体がエラーを起こすため、無効です。 autorunが最終的に実行してmapの地図を更新すると、 'X'を再度更新する必要があります。

溶液を「X」にすることであるのみmapのマップに依存し、単に参照mapこのマップ内の元mapのエントリを格納します。

index.js:

import Inferno from 'inferno' 
import { Provider } from 'inferno-mobx' 
import h from 'inferno-hyperscript'; 

// Components: 
import App from './inferno_components/App.js'; 

// Stores: 
import languages from './stores/LanguagesStore.js'; 
import ui_state from './stores/LanguageViewState.js'; 


Inferno.render(
    h(Provider, {languages, ui_state}, // the following argument can't be an Array: 
     h(App) 
     ) 
, document.getElementById('main')); 



// Make random changes post-render to make sure it re-renders: 
languages.set('french', {id: 'french', example: 'Bonjour tout le monde'}); // map already passes the second arg through observable, so we don't need to do it explicitly 
languages.get('french').example = 'Merci boucoup'; 

languages.set('german', {id: 'german', example: 'Gutten tag'}); 
languages.set('swahili', {id: 'swahili', example: 'Rafiki'}); 
languages.delete('german'); 


ui_state.get('english').visible = false; 

コンポーネント/アプリケーション。JS:

// for any component: 
import { connect } from 'inferno-mobx' 
import h from 'inferno-hyperscript'; 

// components to be used in this component: 
import LanguageView from './LanguageView.js'; 


// the App: 
var App = connect(['ui_state'], function({ui_state}){ 
    return h('div', ui_state.keys().map((language_name) => { 
      var state = ui_state.get(language_name); 
      if(state.visible) 
       return h(LanguageView, {language: state.language}); 
      else 
       return h('p', 'Sorry, invisible!'); 
      })) 
    }); 

export default App; 

コンポーネント/ LanguageView.js:

import { connect } from 'inferno-mobx' 
import h from 'inferno-hyperscript'; 


var LanguageView = connect(function({language}){ 
    return h('div', [ 
     h('p', language.id), 
     h('p', language.example) 
     ]); 
    }); 

export default LanguageView; 

店舗/ LanguagesStore.js:

import { observable } from 'mobx' 

const languages = observable.map({ 
    english: { 
     id: 'english', 
     example: 'Hello World' 
     } 
    }); 

export default languages; 

店舗/ LanguageViewState.js:

import { observable, createTransformer, intercept } from 'mobx'; 

import languages from './LanguagesStore.js'; 


const makeUIStateFromLanguage = createTransformer((language) => { 
    return {language, visible: true} 
    }); 


var ui_state = observable.map({}); 

// initialize: 
languages.forEach((language, language_name) => { 
    ui_state.set(language_name, makeUIStateFromLanguage(language)); 
    }); 

// set up automatic updating: 
intercept(languages, function(change_object){ 
    if(change_object.type === 'add'){ 
     ui_state.set(change_object.name, makeUIStateFromLanguage(change_object.newValue)); 
     } 
    else if(change_object.type === 'delete'){ 
     ui_state.delete(change_object.name); 
     } 
    return change_object; // for intercept 
    }); 

export default ui_state; 
0

あなたがあなたの状態に新しいエントリを追加するときに、あなたのUIマップにエントリを追加するのは難しいかもしれませんが、あなたはUIのマップではないとして目に見えるエントリを表示する場合は、あなたがそれをlike thisを行うことができます:

const state = observable.map({ 
    'rf8r4': {id: 'rf8r4', description: 'Get milk'}, 
    '543w4': {id: '543w4', description: 'Code in MobX'}, 
    '099i0': {id: '099i0', description: 'Sleep'} 
}); 

@observer 
class App extends React.Component { 
    @observable visible = asMap({ 
    'rf8r4': {visible: false} 
    }); 
    @computed get visibleState() { 
    const res = []; 
    state.forEach(val => { 
     const item = this.visible.get(val.id); 
     if (!item || item.visible) { 
     res.push(val); 
     } 
    }); 
    return res; 
    } 
    render() { 
    return <div> 
     {this.visibleState.map(el => 
     <div key={el.id} onClick={this.onClick}> {el.description} </div> 
    )} 
    </div>; 
    } 
    onClick =() => { 
    this.visible.set('rf8r4', {visible: true}); 
    }; 
} 
+0

だから私が作りますUIStateマップであり、明示的に明示されたものだけが含まれます。私がマップを照会すると、適切なエントリが見つかった場合、適切でない場合は、使用しようとしているUIプロパティのデフォルト値を使用します(例えば、 'visible = true'または' color = 'green '')。しかし、エントリが状態マップ(つまり、 'Todos')から削除され、UIマップにエントリがある場合、UIマップ内のそのエントリは時間の経過とともにメモリを使い果たすことがありますか? – user1657586

+0

@ user1657586それは良い点です。長時間実行しているアプリケーションで、たとえば'Todos'、それは適切でないかもしれません。 – Tholle

関連する問題