2015-01-09 4 views
37

私はReact/FluxアプリケーションでImmutableJSを使用しようとしています。Immutable.jsとFluxで.toJS()を使用するタイミングは?

私の店はImmutable.Mapのオブジェクトです。

.toJS()はどの時点で使用する必要がありますか?店舗の.get(id)が返品されたときである必要がありますか?または.get('member')

+1

良い質問です。あなたがshouldComponentUpdateでレンダリングを最適化したいのであれば、単純なオブジェクト比較(prevState!== this.state)を行う能力を失って以来、私は店でそれをやりません。 –

+0

本当に店内で 'toJS()'を使わないのは良い点です。 – chollier

答えて

1

@Hummlasによって良い点が提起されました。

私はpersonnally私は、サブコンポーネントの配列をレンダリングするために、コレクションを反復処理する際に、部品を反応させるのに私にそれを使用

this.props.myImmutableCollection.map(function(item, index) { 
    React.DOM.div null, item.get('title'); 
}).toJS(); 

あなたが.toJSを(使用しない場合)、リアクトは認識しませんマップされた要素をコンポーネントの配列として返します。

42

理想的には決してありません!

FluxストアがImmutable.jsを使用している場合は、すべての方法を維持してください。 React.addons.ReactComponentWithPureRenderMixinを使用して、メモのパフォーマンスを上げます(shouldComponentUpdateメソッドを追加します)。これは、中に変更されている

render: function() { 
    return (
    <div> 
     {this.props.myImmutable.map(function (item) { 
     <div>{item.title}</div> 
     }).toJS()} 
    </div> 
); 
} 

がv0.13.x.に反応:レンダリングする場合v0.12.x反応する

、あなただけの子としてArrayを受け入れtoJS()を呼び出す必要があるかもしれませんコンポーネントは、Arrayではなく、Iterableを子として受け取ります。 Immutable.jsは、反復処理可能を実装しているので、あなたはtoJS()を省略することができません:

render: function() { 
    return (
    <div> 
     {this.props.myImmutable.map(function (item) { 
     <div>{item.title}</div> 
     })} 
    </div> 
); 
} 
+4

Lee、プロタイプのアドバイスはありますか?私は 'arrayOf(shape ...)'を使うのに慣れています。 – Zach

+0

私の外部ライブラリだけでもImmutable.jsをサポートしている場合 – pherris

+4

ReactコンポーネントのImmutable.jsから読み込んだAPI( 'get()'、 'getIn()')を使うのは正しいことですか?これはリーキーな抽象化のように感じています。つまり、店舗での状態をどのように維持するかを変えれば、値を読み取るすべてのコンポーネントに触れなければならないということです。何かこれについて間違っていると感じます... – sethro

0

- もはやお勧めします -
Reduxのを使用しているとき、私は私のコネクトmapStateToPropsはtoJSを(使用して不変の構造を変換機能できるようにする傾向があります)私の反応コンポーネントがjavascriptオブジェクトとして小道具を消費することを可能にする。

+3

しかし、toJSは新しいdeeplycloneオブジェクトを返します。演技には向いていません。 –

+0

これは当てはまりますが、再選択のようなものを使用すると、元の不変オブジェクトが変更された場合にのみ新しいオブジェクトを返すことができます。唯一の問題はネストされたデータです。たとえば、List of Mapの1つの要素だけが変更された場合、新しいオブジェクトを含む新しい配列が返され、各子ビューでレンダリングがトリガされます。変更不能な子供だけが再レンダリングされます... – Ingro

+3

パフォーマンスのために私が提案したことをやめました。 – walkerrandophsmith

3

最近の質問ですが、最近、私はreselectlodash's memoizeを使ってこのアプローチを実験しています。これは、同等のオブジェクトをReactのコンポーネントに返すためです。

import { List, Map } from 'immutable'; 
import { createSelector } from 'reselect'; 
import _ from 'lodash'; 

const store = { 
    todos: List.of(
     Map({ id: 1, text: 'wake up', completed: false }), 
     Map({ id: 2, text: 'breakfast', completed: false }) 
    ) 
}; 

const todosSelector = state => state.todos; 

function normalizeTodo(todo) { 
    // ... do someting with todo 
    return todo.toJS(); 
} 

const memoizeTodo = _.memoize(normalizeTodo); 

export const getTodos = createSelector(
    todosSelector, 
    todos => todos.map(memoizeTodo) 
); 

は、その後、私はTodoList成分プロップとしてtodosに渡す、2つのTodoItemコンポーネントにマッピングされる:

class TodoList extends React.Component { 
    shouldComponentUpdate(nextProps) { 
     return this.props.todos !== nextProps.todos; 
    } 

    render() { 
     return (<div> 
      {this.props.todos.map(todo => <TodoItem key={todo.id} todo={todo} />)} 
     </div>); 
    } 
} 

class TodoItem extends React.Component { 
    shouldComponentUpdate(nextProps) { 
     return this.props.todo !== nextProps.todo; 
    } 

    // ... 
} 

このよう

このような店舗を持っている想像私がgetTodos()と呼ぶとき、todosストアで何も変わっていなければ、私は同じオブジェクトを返すので、何も再描画されません。

たとえば、id 2 siを持つtodoが完了とマークされている場合、ストア内でも変更され、新しいオブジェクトがtodosSelectorによって返されます。次にtodosはmemoizeTodo関数によってマップされます。これはtodoが変更されていない場合(immutableマップなので)同じオブジェクトを返すはずです。だからTodoListが新しい小道具を受け取ったときにはtodosが変更されたので再レンダリングされますが、id35のtodoを表すオブジェクトは変更されないため、2番目のTodoItemが再レンダリングされます。

これは確かに私たちの店にたくさんのアイテムが含まれている場合はパフォーマンスの低下につながる可能性がありますが、私の中型アプリでは何の問題も気づいていません。このアプローチの利点は、コンポーネントが普通のjavascriptオブジェクトを小道具として受け取り、PureRenderMixinのようなもので使用できるため、ストアからオブジェクトを返す方法がもうコンポーネントのビジネスではないことです。

希望、これは理にかなって、私の英語は非常に悪いです:/

+0

素晴らしいソリューション! –

3

@LeeByronあなたはtoJSを呼び出す必要はありません、言ったように。 。下で働くと、正しくレンダリングされます不変Mapmapを呼び出し、* 0.14に反応しますが、エンドアップします警告で:

はまだ完全にはサポートされていない子としてマップを使用。これは削除される可能性のある実験的な機能です。代わりにキー付きReactElementsのシーケンス/ iterableに変換してください。

はこれに対処するために、あなたはあなたの Map等に toArray()を呼び出すことができます。

render() { 
    return (
    <div> 
     {this.props.immutableMap.toArray().map(item => { 
     <div>{item.title}</div> 
     })} 
    </div> 
) 
} 

配列にあなたのiterableを変換し、それが何を望んでリアクト与えます。

+0

あなたの答えはありがとうございました。 – user2861799

+0

@ user2861799ようこそ、うれしいです:) –

関連する問題