【问题标题】:Is it okay to connect a PureComponent?可以连接 PureComponent 吗?
【发布时间】:2018-12-27 15:10:16
【问题描述】:

我想知道这是否可以:

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 会降低性能...

【问题讨论】:

  • 你为什么要做这样的事情?你的动机是什么?它看到你没有使用状态减速器中的任何东西..
  • PureComponents 会降低性能 - 您从哪里听说的?
  • IMO 如果它纯粹是一个 UI 组件,可以在您的应用程序中使用不同的数据重复使用,我会将 props 传递给 ListItem 并避免将其连接到 Redux。
  • @hodcaspi 我还没有这样做。我在编写 ListItem 的过程中问了这个问题,想知道我要做的事情是否可以。因此mapStateToProps() 尚未实现:)
  • @dbvt10 降低性能可能是错误的,但请查看 React Native 文档中的警告:facebook.github.io/react-native/docs/flatlist

标签: reactjs react-native redux react-redux react-component


【解决方案1】:

纯组件对 props 进行浅层比较,只有在 props 发生变化时才会重新渲染。

connect(HOC) 还根据比较进行浅层比较和重新渲染。

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

在使用connect时避免使用纯组件。

【讨论】:

    【解决方案2】:

    实际上connect() 函数默认使包装的组件成为纯组件(参见docs)。也就是说,只有当属性发生变化(状态或自己的道具)时,才会重新渲染被包装的组件。所以继承PureComponent没有意义,因为shouldComponentUpdate逻辑已经在connect()生成的HOC中实现了。

    我听说 PureComponents 会降低性能...

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

    【讨论】:

    • 你错了,因为 HOC 不会比较组件的状态,但 PureComponent 会。所以如果组件有自己的状态,那么使用 PureComponent 是有意义的。
    【解决方案3】:

    我在使用连接组件的列表项时遇到了问题,并在谷歌搜索后出现在这里。

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

    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 将返回与上次相同的引用,列表中所有未更改的项目都将重新呈现。

    我一直以为 connect 会返回一个纯组件,但我错了,解决方案是让 Item 成为一个纯组件,使用 React.memo 这很简单:

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

    Item 是一个功能组件 (props=&gt;jsx)。

    当您更改列表中一个项目的编辑模式时,edit 属性将为所有项目更改,但感谢 defaultMemoize 并从 mapStateToProps 返回一个函数,该函数创建了一个记忆化的 createMergedItem 函数,它将返回与最后一个具有相同引用的道具。这还不够,因为仍然调用了 Item 函数。我还必须使用 React.memo 使 Item 成为纯组件。

    【讨论】:

      【解决方案4】:

      使用 connect 和 PureComponent 没有问题。 PureComponent 会在 props 发生变化时渲染,connect() 将 redux 状态映射到 props。请参阅 redux 团队的 this example。我已经用 Purecomponent 替换了 TodoList 组件:

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

      它的工作原理是一样的。

      【讨论】:

      • “PureComponent 会在 props 发生变化时渲染……”但只是浅显的。做出区分很重要。
      • 是的。但是,如果您在您的 redux 项目中使用“不可变”(我推荐),那么出现此类错误的可能性非常低。根据我的经验,问题往往是相反的。组件渲染过于频繁,因为mapStateToProps 总是返回新对象。
      • 感谢您的精心解答!会用这个:)
      猜你喜欢
      • 2018-09-23
      • 2011-03-02
      • 1970-01-01
      • 1970-01-01
      • 2021-12-17
      • 1970-01-01
      • 2020-12-25
      • 1970-01-01
      相关资源
      最近更新 更多