javascript - 我必须在 React 钩子中使用扩展运算符的原因是什么?
问题描述
预期行为
每次点击时渲染计数器增加一个
实际行为
渲染计数器不会增加,但内部会增加(如警报消息所示)。看看这个截图: http: //prntscr.com/ujtsu9(它不会一直发生..)
代码
import React, { Component, useState } from "react";
import "./App.css";
function App(props) {
const [all, setAll] = useState([{ name: "PHP", votes: 1 }]);
function changeAll() {
const newAll = all;
alert(newAll === all); //alert true
newAll[0].votes++;
setAll(newAll);
alert(all[0].votes);
}
return (
<>
<div className="voteCount">{all[0].votes}</div>
<div className="lanugageName">{all[0].name}</div>
<button onClick={changeAll}>Click Here</button>
</>
);
}
export default App;
我试过的:
将行const newAll = all;
-> 更改为 ->const newAll = [...all];
然后它可以工作。但是,然后警报说“假”
问题
- 为什么我需要使用扩展运算符?
- 如果我使用扩展运算符,为什么是
newAll === all
假的?
解决方案
为什么我需要使用扩展运算符?
您不需要使用扩展语法*,但您确实需要将要变异的现有状态浅层复制到新的对象/数组/内存引用中。使用扩展语法是实现此目的的方法之一。使用数组时,通常会使用许多返回新数组的数组函数,即映射、过滤器、切片。
如果我使用扩展运算符 [语法*]为什么是
newAll === all
假的?
当您const newAll = all
还将对状态的引用保存到时all
,newAll
但是您const newAll = [...all]
首先将状态传播到新的数组引用中,然后将其保存到newAll
试试看
const all = [1,2,3];
const newAll1 = all;
const newAll2 = [...all];
console.log(newAll1 === all); // true
console.log(newAll2 === all); // false
*传播语法
我还想提醒你不要使用这样的模式
newAll[0].votes++;
setAll(newAll);
即使您浅拷贝all
,newAll[0].votes++
仍然会被视为状态突变。如果您需要更新处于反应状态的数组元素,那么您还应该浅拷贝您打算更新的任何对象的属性。
setAll(all.map((el, index) => !index ? el : { ...el, votes: el.votes + 1 }))
更重要的是,如果任何状态更新依赖于现有状态(增加计数是默认示例,顺便说一句),您将希望使用功能更新。
setAll(all => all.map((el, index) => !index ? el : { ...el, votes: el.votes + 1 }))
推荐阅读
- java - 在 Junit,Mockito 中模拟局部变量
- flutter - Flutter PopupMenuButton 填充或全宽
- python - 你能在 Python 上使用 SimPy 做一个闭环系统吗?
- node.js - [SequelizeDatabaseError]:Sequelize 中的列名“userId”重复?
- python - 如何从 yahoo.finance 中提取 beta 数据?
- python - Django Paginator 在第一页后不起作用
- flutter - flutter params 数组在 api 请求中被字符串化
- python - Python lambda 列表:函数中列表理解、for 和 for 的不同行为
- html - Visual Studio Code 实时服务器
- php - CORS Ajax 请求:Set-Cookie 失败