javascript - 需要帮助简化 Immutable.js 对象数组更新
问题描述
我是 immutablejs 的新手,并且设法更新了存储在对象数组中的对象的属性。我的目标是简化我的开发,但我觉得我让它变得更复杂了。显然,我错过了一些让这更简单的东西。
我创建了一个 stackblitz 项目,一个是没有 immutablejs https://stackblitz.com/edit/react-before-immutable的代码,一个是 immutablejs https://stackblitz.com/edit/react-after-immutable
(下面的代码也是)。
我在这里看到了一些示例,人们使用 findIndex 的第二个参数,但该函数从未被我调用过。它也不在文档中,所以我猜它不再受支持。
使用 Immutable.js
import React, { useState } from 'react';
import { List } from 'immutable';
export default () => {
const init = [{
id: 101,
interestLevel: 1
},
{
id: 102,
interestLevel: 0
}];
const [myArray, setMyArray] = useState(init);
const updateRow = (e) => {
const id = parseInt(e.target.attributes['data-id'].value);
const immutableMyArray = List(myArray);
const index = List(myArray).findIndex((item) => {
return item.id === id;
});
const myRow = immutableMyArray.get(index);
myRow.interestLevel++;
const newArray = immutableMyArray.set(index, myRow);
setMyArray(newArray);
};
return (
<ul>
{
myArray.map(function (val) {
return (
<li key={val.id}>
<button onClick={updateRow} data-id={val.id} >Update Title</button>
{val.id} : {val.interestLevel}
</li>
)
})
}
</ul>
)
}
没有 Immutable.js
import React, { useState } from 'react';
export default () => {
const init = [{
id: 101,
interestLevel: 1
},
{
id: 102,
interestLevel: 0
}];
const [myArray, setMyArray] = useState(init);
const updateRow = (e) => {
const id = e.target.attributes['data-id'].value;
const newMyArray = [...myArray];
var index = newMyArray.findIndex(a=>a.id==id);
newMyArray[index].interestLevel = myArray[index].interestLevel + 1;
setMyArray(newMyArray);
}
return (
<ul>
{
myArray.map(function (val) {
return (
<li key={val.id}>
<button onClick={updateRow} data-id={val.id} >Update Title</button>
{val.id} : {val.interestLevel}
</li>
)
})
}
</ul>
)
}
解决方案
你考虑过 immutablejs 的目的吗?
在您的示例中,您只是在代码中添加了不必要的复杂性,而没有利用库提供的收益。
不可变的目的是提供不可变的集合,灵感来自 scala。换句话说,您创建了您的集合,然后将它传递给另一个组件,您可以确定没有元素被添加或删除。但是,个别元素不受此类保证,部分原因是 JS 带来的限制(或缺乏限制)。
正如您的代码中所代表的那样,做这样的事情的理由很少。为了展示如何做到这一点,我冒昧地更改了您的报价:
class Comp extends React.Component {
constructor(props) {
super(constructor);
if (props.interests) {
this.state = {
interests: props.interests
}
} else {
this.state = {
interests: Immutable.Set([])
}
}
}
updateRow(e) {
return function() {
this.setState({
interests: this.state.interests.update((elements) => {
for (var element of elements) {
if (element.id == e) {
element.interestLevel++;
}
}
return elements;
})
});
}
}
render() {
var interests = this.state.interests;
var updateRow = this.updateRow;
var list = this;
//return (<div>Test</div>);
return ( <
ul > {
interests.map(function(val) {
return ( <
li key = {
val.id
} >
<
button onClick = {
updateRow(val.id).bind(list)
}
data-id = {
val.id
} > Update Title < /button> {
val.id
}: {
val.interestLevel
} <
/li>
)
})
} <
/ul>
)
}
}
var interests = Immutable.Set([{
id: 1,
interestLevel: 0
},
{
id: 2,
interestLevel: 0
}
])
ReactDOM.render( < Comp interests = {
interests
}
/>, document.getElementById("app"));
<script src="https://cdn.jsdelivr.net/npm/immutable@4.0.0-rc.12/dist/immutable.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.7.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.7.0/umd/react-dom.production.min.js"></script>
<div id='app'></div>
变化:
- 将您的组件重写为一个类。这纯粹是为了突出其余的变化
prop
您的组件现在需要一个包含兴趣的外部组件。这意味着您可以传递 aSet
并确保它不会在组件中突然添加元素- 该组件负责利息水平。因此,每当您单击其中一个按钮时,都会在 上
update
调用该函数,该函数Set
用于更新集合中的项目 - 整个事情通过
render()
这既更具可读性,也更易于管理。
推荐阅读
- qt - QT ModelView:在 QAbstractItemModel 中使用共享指针的示例
- python - 为什么不能将 NaN 的 pandas 数据框值用作字典键?
- javascript - Youtube 音频立体声声像
- dart - 正好两种类型的 Dart 列表
- android - 如何使用 SHA256 算法签署 .apk
- docusignapi - DSA Web 应用程序和客户端应用程序上的 DocuSign 基本 URL 和资源路径位置
- keycloak - Keycloak 向客户端添加资源
- linux - IO 到固定内存
- imagemagick - 有没有办法使用 ImageMagick 在图像周围绘制边框?
- anylogic - 在任意逻辑参数变化实验中显示模拟进度百分比