连接一个 PureComponent 可以吗?

Is it okay to connect a 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 会降低性能...

使用connect和PureComponent没有问题。 PureComponent 在 props 发生变化时渲染,connect() 将 redux 状态映射到 props。请参阅 redux 团队的 this example。我已将 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>
)
*/

效果一样。

我对连接组件的列表项有问题,在谷歌搜索后最终出现在这里。

我会在这里添加问题的描述和我的解决方案:

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.id 作为键。如果我有一个 ID 为 1 的项目并且编辑为 {1:anythingTruthy},那么项目 1 处于编辑模式。

当我将列表中的项目从编辑模式更改为或更改为编辑模式时,列表中所有未更改的项目将重新呈现,即使 mapStateToProps 将 return 与上一个相同的引用时间.

我一直认为 connect 会 return 一个纯组件,但我错了,解决方案是使 Item 成为一个纯组件,并且使用 React.memo 这非常简单:

import { memo } from 'react';
//mapStateToProps is the same
export default connect(
  mapStateToProps,
)(memo(Item));//wrap Item in memo

其中 Item 是功能组件 (props=>jsx)。

当您更改列表中一项的编辑模式时,所有项的 edit 属性都会更改,但感谢 defaultMemoize 和 returning 来自 [=13= 的函数] 创建一个记忆化的 createMergedItem 函数,它将 return props 与上一个具有相同的引用。这还不够,因为 Item 函数仍然被调用。我还必须使用 React.memo 使 Item 成为纯组件。

实际上 connect() 函数在默认情况下使包装组件成为纯组件(参见 docs)。也就是说,只有当属性发生变化(state 或 own props)时,才会重新渲染被包装的组件。所以从 PureComponent 继承是没有意义的,因为 shouldComponentUpdate 逻辑已经在 connect().

产生的 HOC 中实现了

I've heard that PureComponents can slow down performance...

PureComponent 执行的浅层道具比较是相对便宜的操作。我认为这不会成为问题。

纯组件对 props 进行浅层比较,re-renders 仅当 props 发生变化时。

connect(HOC) 也进行浅层比较,re-rendering 基于比较。

两者做同样的工作。所以在同一个组件中同时使用两者并没有什么坏处,但是在同时使用两者时,post connect 会进行比较,纯组件也会进行浅层比较。这是重复的,可能会花费时间。

避免在使用连接时使用纯组件。