43

React / Flux アプリケーションで ImmutableJS を使用しようとしています。

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

どの時点で使用する必要があるか疑問に思っています.toJS()。店が.get(id)戻ってきたときでしょうか?またはコンポーネントで.get('member')

4

5 に答える 5

5

少し古い質問ですが、最近、React のコンポーネントに匹敵するオブジェクトを返すために、reselectlodash の 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 つのコンポーネントにマップされます。todosTodoItem

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ます。次に、memoizeTodotodo は関数によってマップされます。todo が変更されていない場合、関数は同じオブジェクトを返す必要があります (それらは不変マップであるため)。したがってTodoList、 が新しい props を受け取ると、 が変更されたために再レンダリングされますが、id 1 の todo を表すオブジェクトtodosが変更されていないため、2 番目のみが再レンダリングされます。TodoItem

特に私たちのストアに多くのアイテムが含まれている場合、これは確かにパフォーマンスの低下につながる可能性がありますが、中規模のアプリでは問題に気付きませんでした. このアプローチの利点は、コンポーネントがプレーンな JavaScript オブジェクトを props として受け取り、それらを のようなもので使用できることですPureRenderMixin。そのため、オブジェクトがストアから返される方法は、もはやコンポーネントの仕事ではありません。

于 2016-01-20T09:30:51.453 に答える
3

@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 に必要なものを与えます。

于 2016-03-09T00:48:36.313 に答える
2

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

コレクションを反復処理してサブコンポーネントの配列をレンダリングするときに、React コンポーネントで個人的に使用します。

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

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

于 2015-01-12T16:26:49.177 に答える
0

-- もうお勧めしません --
Redux を使用する場合、connects の mapStateToProps 関数が toJS() を使用して不変の構造を変換し、react コンポーネントが props を JavaScript オブジェクトとして消費できるようにする傾向があります。

于 2016-01-04T01:58:15.090 に答える