私はこれが大丈夫かどうか疑問に思っていました:
_import React, { PureComponent } from "react";
import { Text, TouchableOpacity } from "react-native";
import { connect } from "react-redux";
import PropTypes from "prop-types";
class ListItem extends PureComponent {
render() {
return (
<TouchableOpacity>
<Text style={{ color: "red" }}>Some Text</Text>
<TouchableOpacity />
</TouchableOpacity>
);
}
}
export default connect()(ListItem);
_
そして、おそらくmapStateToProps()
を追加します。それともこれはアンチパターンですか? PureComponentsがパフォーマンスを低下させる可能性があると聞きました...
ConnectおよびPureComponentの使用には問題はありません。 PureComponentは、プロップが変更され、connect()
がreduxの状態をプロップにマップした場合にレンダリングします。 reduxチームによる この例 を参照してください。 TodoListコンポーネントをPurecomponentに置き換えました。
class TodoList extends React.PureComponent {
render() {
const { todos, toggleTodo } = this.props;
return (
<ul>
{todos.map(todo => (
<Todo key={todo.id} {...todo} onClick={() => toggleTodo(todo.id)} />
))}
</ul>
);
}
}
/*
const TodoList = ({ todos, toggleTodo }) => (
<ul>
{todos.map(todo =>
<Todo
key={todo.id}
{...todo}
onClick={() => toggleTodo(todo.id)}
/>
)}
</ul>
)
*/
まったく同じように機能します。
実際にconnect()
関数は、ラップされたコンポーネントをデフォルトで純粋にします( docs を参照)。つまり、ラップされたコンポーネントは、プロパティが変更されたときにのみレンダリングされます(状態または独自のプロップ)。したがって、shouldComponentUpdate
ロジックはconnect()
によって生成されたHOCにすでに実装されているため、PureComponentから継承しても意味がありません。
PureComponentsがパフォーマンスを低下させる可能性があると聞きました...
PureComponentによって実行される浅い小道具の比較は、比較的安価な操作です。それが問題になるとは思わない。
接続されたコンポーネントであるリストアイテムに問題があり、グーグルした後、ここに行きました。
ここに問題の説明と私の解決策を追加します。
mapStateToProps
は次のようになります
import { defaultMemoize } from 'reselect';
const mapStateToProps = () => {
const createMergedItem = defaultMemoize((item, edit) =>
edit
? { ...item, edit: true }
: { ...item, edit: false }
);
return (state, { item, edits }) => {
//returning same ref when item and edits[item.id] didn't change
return createMergedItem(item, Boolean(edits[item.id]));
};
};
export default connect(
mapStateToProps,
)(Item);
リストコンポーネント内
items.map(item=>(<Item key={item.id} item={item} edit={edit} />)
コードは少し簡略化されていますが、Listがアイテムを渡し、各Itemコンポーネントにプロップとして編集します。編集は、item.idをキーとするメンバーを持つオブジェクトです。 id 1のアイテムがあり、editsが{1:anythingTruthy}
の場合、アイテム1は編集モードです。
リストの項目を編集モードから、または編集モードに変更すると、mapStateToPropsが前回と同じ参照を返しても、変更されていないリストのすべての項目が再表示されます。
Connectは純粋なコンポーネントを返すといつも思っていましたが、私は間違っていました。解決策は、Itemを純粋なコンポーネントにし、 React.memo を使用することです。これは非常に簡単です。
import { memo } from 'react';
//mapStateToProps is the same
export default connect(
mapStateToProps,
)(memo(Item));//wrap Item in memo
Itemは機能コンポーネントです(props=>jsx
)。
リスト内の1つのアイテムの編集モードを変更すると、edit
プロップはすべてのアイテムに対して変更されますが、defaultMemoize
と、メモ化されたmapStateToProps
関数を作成するcreateMergedItem
から関数を返すおかげで、最後のものと同じ参照を持つ小道具が返されます。 Item関数がまだ呼び出されているため、これでは不十分でした。また、React.memo
を使用して、Itemを純粋なコンポーネントにする必要がありました。