React/FluxアプリケーションでImmutableJSを使用しようとしています。
私のストアは_Immutable.Map
_オブジェクトです。
どの時点で.toJS()
を使用すべきか疑問に思っていますか?ストアの.get(id)
が戻るときですか?または.get('member')
のあるコンポーネントで?
理想的には、決して!
FluxストアがImmutable.jsを使用している場合は、ずっと維持するようにしてください。 React.addons.ReactComponentWithPureRenderMixinを使用して、メモ化のパフォーマンスを向上させます(shouldComponentUpdateメソッドが追加されます)。
レンダリングするとき、toJS()
をReact v0.12.xは子としてArray
のみを受け入れるように呼び出す必要があります:
render: function () {
return (
<div>
{this.props.myImmutable.map(function (item) {
<div>{item.title}</div>
}).toJS()}
</div>
);
}
これはReact v0.13.x.で変更されました。コンポーネントはArray
だけではなく子としてIterableを受け入れます。Immutable.jsはIterableを実装するため、toJS()
:
render: function () {
return (
<div>
{this.props.myImmutable.map(function (item) {
<div>{item.title}</div>
})}
</div>
);
}
ちょっと古い質問ですが、最近、 reselect と lodash'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;
}
// ...
}
_
このように、todoのストアで何も変更がなければ、getTodos()
reselectを呼び出すと同じオブジェクトが返されるため、何も再レンダリングされません。
たとえば、IDが_2
_のtodoが完了とマークされている場合、ストアでも変更されるため、todosSelector
によって新しいオブジェクトが返されます。次に、todoはmemoizeTodo
関数によってマップされます。この関数は、todoが変更されない場合は同じオブジェクトを返す必要があります(不変マップであるため)。したがって、TodoList
は新しい小道具を受け取ると、todos
が変更されたため再レンダリングされますが、id 1のtodoを表すオブジェクトが変更されたため、2番目のTodoItem
のみが再レンダリングされます変わらない。
これは、特にストアに多くのアイテムが含まれている場合にパフォーマンスの低下につながる可能性がありますが、中規模アプリでは問題に気付きませんでした。このアプローチの利点は、コンポーネントが小道具としてプレーンなJavaScriptオブジェクトを受け取り、PureRenderMixin
のようなものでそれらを使用できるため、ストアからオブジェクトが返される方法はコンポーネントのビジネスではなくなります。
@LeeByronが言ったように、toJS
を呼び出す必要はありません。 React 0.14。*)で、不変のmap
でMap
を呼び出すと機能し、正しくレンダリングされますが、警告が表示されます:
Mapsを子として使用することはまだ完全にはサポートされていません。これは実験的な機能であり、削除される可能性があります。代わりに、キー付きReactElementsのシーケンス/反復可能に変換します。
これに対処するには、Map
でtoArray()
を次のように呼び出すことができます。
render () {
return (
<div>
{this.props.immutableMap.toArray().map(item => {
<div>{item.title}</div>
})}
</div>
)
}
イテラブルを配列に変換し、React欲しいものを与える。
@Hummlasによる良い点。
サブコンポーネントの配列をレンダリングするためにコレクションを反復処理するときに、Reactコンポーネントで個人的に使用します:
this.props.myImmutableCollection.map(function(item, index) {
React.DOM.div null, item.get('title');
}).toJS();
.toJS()を使用しない場合、Reactはマップされた要素をコンポーネントの配列として認識しません。
-推奨されなくなりました-
[。