连接一个 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 会进行比较,纯组件也会进行浅层比较。这是重复的,可能会花费时间。
避免在使用连接时使用纯组件。
我想知道这是否可以:
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()
.
I've heard that PureComponents can slow down performance...
PureComponent 执行的浅层道具比较是相对便宜的操作。我认为这不会成为问题。
纯组件对 props 进行浅层比较,re-renders 仅当 props 发生变化时。
connect(HOC) 也进行浅层比较,re-rendering 基于比较。
两者做同样的工作。所以在同一个组件中同时使用两者并没有什么坏处,但是在同时使用两者时,post connect 会进行比较,纯组件也会进行浅层比较。这是重复的,可能会花费时间。
避免在使用连接时使用纯组件。