react 状态不变_在React中处理状态:需要考虑的四种不变方法

react 状态不变

by Cory House

由科里·豪斯(Cory House)设计

Perhaps the most common point of confusion in React today: state.

今天,React中最常见的混乱点是:状态。

Imagine you have a form for editing a user. It’s common to create a single change handler to handle changes to all form fields. It may look something like this:

假设您有一个用于编辑用户的表单。 创建单个更改处理程序来处理所有表单字段的更改是很常见的。 它可能看起来像这样:

updateState(event) {
 const {name, value} = event.target;
 let user = this.state.user; // this is a reference, not a copy...
 user[name] = value; // so this mutates state ?
 return this.setState({user});
}

The concern is on line 4. Line 4 actually mutates state because the user variable is a reference to state. React state should be treated as immutable.

问题在第4行上。第4行实际上是对状态进行突变,因为用户变量是对状态的引用 。 React状态应视为不可变的。

From the React docs:

React docs

Never mutate this.state directly, as calling setState() afterwards may replace the mutation you made. Treat this.state as if it were immutable.

切勿直接this.state ,因为之后调用setState()可能会替换您所做的this.statethis.state视为不可变的。

Why?

为什么?

  1. setState batches work behind the scenes. This means a manual state mutation may be overridden when setState is processed.

    setState批处理在后台进行。 这意味着在处理setState时可以覆盖手动状态突变。
  2. If you declare a shouldComponentUpdate method, you can’t use a === equality check inside because the object reference will not change. So the approach above has a potential performance impact as well.

    如果声明了shouldComponentUpdate方法,则不能在内部使用===相等检查,因为对象引用不会更改 。 因此,上述方法也可能会对性能产生影响。

Bottom line: The example above often works okay, but to avoid edge cases, treat state as immutable.

底线 :上面的示例通常可以正常工作,但要避免出现极端情况,请将状态视为不可变的。

Here are four ways to treat state as immutable:

以下是将状态视为不可变的四种方法:

方法1:Object.assign (Approach 1: Object.assign)

Object.assign creates a copy of an object. The first parameter is the target, then you specify one or more parameters for properties you’d like to tack on. So fixing the example above involves a simple change to line 3:

Object.assign创建对象的副本。 第一个参数是目标,然后为要添加的属性指定一个或多个参数。 因此,修复上面的示例涉及对第3行的简单更改:

updateState(event) {
 const {name, value} = event.target;
 let user = Object.assign({}, this.state.user);
 user[name] = value;
 return this.setState({user});
}

On line 3, I’m saying “Create a new empty object and add all the properties on this.state.user to it.” This creates a separate copy of the user object that’s stored in state. Now I’m safe to mutate the user object on line 4 — it’s a completely separate object from the object in state.

在第3行中,我说的是“创建一个新的空对象,并将this.state.user上的所有属性添加到其中。” 这将创建状态存储的用户对象的单独副本。 现在,我可以安全地更改第4行上的用户对象-它是与处于状态状态的对象完全独立的对象。

Be sure to polyfill Object.assign since it’s unsupported in IE and not transpiled by Babel. Four options to consider:

请确保pol

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用 React 和 Ant Design Pro 实现轮播表格的数据表头 columns 不的示例代码。 首先,我们需要引入 `Carousel` 和 `Table` 组件以及相应的样式文件。 ```tsx import { Carousel, Table } from 'antd'; import 'antd/dist/antd.css'; import styles from './index.less'; ``` 接着,我们定义一个函数组件 `CarouselTable`,它接收 `data` 和 `columns` 两个参数。 ```tsx interface Props { data: any[]; columns: any[]; } const CarouselTable: React.FC<Props> = ({ data, columns }) => { // TODO: 实现轮播表格逻辑 return ( <div className={styles.carouselTable}> {/* TODO: 渲染轮播表格 */} </div> ); }; ``` 接下来,我们在 `CarouselTable` 组件实现轮播表格的逻辑。我们使用 `Carousel` 组件来实现轮播效果,并在每个轮播项渲染一个 `Table` 组件来显示表格数据。 ```tsx const CarouselTable: React.FC<Props> = ({ data, columns }) => { const pageSize = 5; // 每页显示的数据条数 const pageCount = Math.ceil(data.length / pageSize); // 总页数 const tableData = Array.from({ length: pageCount }, (_, i) => data.slice(i * pageSize, (i + 1) * pageSize) ); // 将数据分页 return ( <div className={styles.carouselTable}> <Carousel dots={false} autoplay> {tableData.map((pageData, i) => ( <div key={i}> <Table dataSource={pageData} columns={columns} pagination={false} /> </div> ))} </Carousel> </div> ); }; ``` 在这段代码,我们首先计算出总页数和每页显示的数据条数,然后将数据分页。接着,我们使用 `Carousel` 组件来渲染轮播项,每个轮播项渲染一个 `Table` 组件来显示分页后的数据。注意,我们将 `pagination` 属性设置为 `false`,以避免在每个表格显示分页条。 最后,我们导出 `CarouselTable` 组件。 ```tsx export default CarouselTable; ``` 完整代码示例: ```tsx import { Carousel, Table } from 'antd'; import 'antd/dist/antd.css'; import styles from './index.less'; interface Props { data: any[]; columns: any[]; } const CarouselTable: React.FC<Props> = ({ data, columns }) => { const pageSize = 5; // 每页显示的数据条数 const pageCount = Math.ceil(data.length / pageSize); // 总页数 const tableData = Array.from({ length: pageCount }, (_, i) => data.slice(i * pageSize, (i + 1) * pageSize) ); // 将数据分页 return ( <div className={styles.carouselTable}> <Carousel dots={false} autoplay> {tableData.map((pageData, i) => ( <div key={i}> <Table dataSource={pageData} columns={columns} pagination={false} /> </div> ))} </Carousel> </div> ); }; export default CarouselTable; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值