React / Flux アプリケーションで ImmutableJS を使用しようとしています。
私の店はImmutable.Map
オブジェクトです。
どの時点で使用する必要があるか疑問に思っています.toJS()
。店が.get(id)
戻ってきたときでしょうか?またはコンポーネントで.get('member')
?
React / Flux アプリケーションで ImmutableJS を使用しようとしています。
私の店はImmutable.Map
オブジェクトです。
どの時点で使用する必要があるか疑問に思っています.toJS()
。店が.get(id)
戻ってきたときでしょうか?またはコンポーネントで.get('member')
?
少し古い質問ですが、最近、React のコンポーネントに匹敵するオブジェクトを返すために、reselectとlodash の memoizeを使用してこのアプローチを試しています。
次のような店舗があるとします。
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)
);
次に、prop としてTodoList
コンポーネントに渡します。これは、2 つのコンポーネントにマップされます。todos
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 の todo が2
完了としてマークされている場合、ストア内でも変更されるため、新しいオブジェクトが によって返されtodosSelector
ます。次に、memoizeTodo
todo は関数によってマップされます。todo が変更されていない場合、関数は同じオブジェクトを返す必要があります (それらは不変マップであるため)。したがってTodoList
、 が新しい props を受け取ると、 が変更されたために再レンダリングされますが、id 1 の todo を表すオブジェクトtodos
が変更されていないため、2 番目のみが再レンダリングされます。TodoItem
特に私たちのストアに多くのアイテムが含まれている場合、これは確かにパフォーマンスの低下につながる可能性がありますが、中規模のアプリでは問題に気付きませんでした. このアプローチの利点は、コンポーネントがプレーンな JavaScript オブジェクトを props として受け取り、それらを のようなもので使用できることですPureRenderMixin
。そのため、オブジェクトがストアから返される方法は、もはやコンポーネントの仕事ではありません。
@LeeByron が言ったように、 a を呼び出す必要はありませんtoJS
。React 0.14.* ではmap
、Immutable の呼び出しMap
は機能し、正しくレンダリングされますが、最終的に警告が表示されます。
マップを子として使用することは、まだ完全にはサポートされていません。これは、削除される可能性のある実験的な機能です。代わりに、キー付き ReactElements のシーケンス / イテラブルに変換してください。
これに対処するには、好きなように呼び出すことができtoArray()
ますMap
:
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 はマップされた要素をコンポーネントの配列として認識しません。
-- もうお勧めしません --
Redux を使用する場合、connects の mapStateToProps 関数が toJS() を使用して不変の構造を変換し、react コンポーネントが props を JavaScript オブジェクトとして消費できるようにする傾向があります。