我想用我的React/Flux應用程序使用ImmutableJS。何時使用.toJS()與Immutable.js和Flux?
我的店是Immutable.Map
對象。
我不知道在這一點,我應該使用.toJS()
?商店的.get(id)
是否應該返回?或在與.get('member')
的組件?通過@Hummlas提出
我想用我的React/Flux應用程序使用ImmutableJS。何時使用.toJS()與Immutable.js和Flux?
我的店是Immutable.Map
對象。
我不知道在這一點,我應該使用.toJS()
?商店的.get(id)
是否應該返回?或在與.get('member')
的組件?通過@Hummlas提出
好一點。
我personnally用它在我的反應的組分,當我遍歷一個集合,以使子組件陣列:
this.props.myImmutableCollection.map(function(item, index) {
React.DOM.div null, item.get('title');
}).toJS();
如果你不使用.toJS(),陣營將無法識別映射元素作爲組件數組。
理想的情況下,從來沒有!
如果你的流量商店使用Immutable.js然後試圖通過維持所有的方式。使用React.addons.ReactComponentWithPureRenderMixin實現memoization性能贏(它增加了一個shouldComponentUpdate方法)。
渲染時,您可能需要調用toJS()
爲陣營v0.12.x只接受Array
兒童:
render: function() {
return (
<div>
{this.props.myImmutable.map(function (item) {
<div>{item.title}</div>
}).toJS()}
</div>
);
}
這已經改變作出反應v0.13.x.組件接受任何Iterable作爲孩子,而不僅僅是Array
。由於Immutable.js實現可迭代,你可以省略toJS()
:
render: function() {
return (
<div>
{this.props.myImmutable.map(function (item) {
<div>{item.title}</div>
})}
</div>
);
}
- 不再推薦 -
當使用終極版我傾向於讓我的連接mapStateToProps函數變換使用toJS不變的結構()並允許我的反應組件使用道具作爲JavaScript對象。
但是,toJS將返回一個新的深度克隆對象。這不利於表演。 –
這是真的,但是使用類似重新選擇的東西,只有當底層的不可變對象發生了變化時才能返回新對象。唯一的問題是嵌套數據。例如,如果地圖列表中只有一個元素髮生了變化,則會返回一個包含新對象的全新數組,並在每個子視圖中觸發一個渲染。隨着不可改變,只有變化後的孩子纔會重新呈現...... – Ingro
因爲表現,我已經停止了我所建議的。 – walkerrandophsmith
有點古老的問題,但最近我正在試驗這種方法,使用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;
}
// ...
}
這樣,如果todos商店沒有任何變化,當我打電話getTodos()
重新選擇返回給我同一個對象,所以沒有重新呈現。
如果例如待辦事項ID爲2 SI標記爲完成,它也改變了存儲,所以一個新的對象被todosSelector
返回。然後,待辦事項由memoizeTodo
函數映射,如果待辦事項未更改(因爲它們是不可變的地圖),該函數應返回相同的對象。所以當TodoList
收到新的道具時,它會重新渲染,因爲todos
已更改,但只有第二個TodoItem
重新渲染,因爲表示id爲1的待辦事項的對象未更改。
這肯定會導致性能損失,特別是如果我們的商店包含很多項目,但我沒有發現我的中型應用程序有任何問題。這種方法的好處是你的組件接收純JavaScript對象作爲道具,並可以像PureRenderMixin
一樣使用它們,所以從商店返回對象的方式不再是組件的業務。
希望這是有道理的,我的英語非常糟糕:/
驚人的解決方案! –
像@LeeByron說,你不應該叫toJS
。下反應0.14 *,調用一個不變的Map
map
將工作和正確渲染,但你會最終了一個警告:
使用地圖作爲孩子還沒有完全支持。這是一個可能會被刪除的實驗性功能。相反,將其轉換爲鍵控ReactElements的序列/迭代。
爲了解決這個問題,你可以在你喜歡Map
打電話toArray()
:
render() {
return (
<div>
{this.props.immutableMap.toArray().map(item => {
<div>{item.title}</div>
})}
</div>
)
}
轉換您可迭代到一個數組中,並給予陣營想要的東西。
謝謝你的回答一直在尋找這麼久! – user2861799
@ user2861799不客氣,很高興幫助:) –
好問題。我不會在商店中做到這一點,因爲如果你想用shouldComponentUpdate優化渲染,那麼你就失去了進行簡單對象比較(prevState!== this.state)的能力。 –
非常感謝,不要在商店中使用'toJS()'。 – chollier