web-dev-qa-db-ja.com

PureComponentを接続しても大丈夫ですか?

私はこれが大丈夫かどうか疑問に思っていました:

_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がパフォーマンスを低下させる可能性があると聞きました...

10
J. Hesters

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>
)
*/

まったく同じように機能します。

5
Sylvain

実際にconnect()関数は、ラップされたコンポーネントをデフォルトで純粋にします( docs を参照)。つまり、ラップされたコンポーネントは、プロパティが変更されたときにのみレンダリングされます(状態または独自のプロップ)。したがって、shouldComponentUpdateロジックはconnect()によって生成されたHOCにすでに実装されているため、PureComponentから継承しても意味がありません。

PureComponentsがパフォーマンスを低下させる可能性があると聞きました...

PureComponentによって実行される浅い小道具の比較は、比較的安価な操作です。それが問題になるとは思わない。

5
AlexM

接続されたコンポーネントであるリストアイテムに問題があり、グーグルした後、ここに行きました。

ここに問題の説明と私の解決策を追加します。

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を純粋なコンポーネントにする必要がありました。

0
HMR