如何在过滤地图列表时更新不可变的键值
How to update key value in immutable while filtering over List of Maps
我有一个不可变列表,如下所示:
this.state = {
suggestedUsers: fromJS([
{
user: {
client_user_id: "1234567890",
full_name: "marty mcfly",
image: "imageURL",
role_name: "Associate Graphic Designer",
selected: false
}
},
{
user: {
client_user_id: "0987654321",
full_name: "doc",
image: "imageURL",
role_name: "Software Engineer",
selected: false
}
}
)]
这用于在 UI 中显示此信息的 div。
当我点击 div 时,我有一个函数被触发,如下所示:
selectUser(clientUserId){
// set assessments variable equal to the current team from the state
let assessments = fromJS(this.state.suggestedUsers)
let selectAssessor
// set a variable called selectedUsers equal to the results of filtering over the current suggestedUsers from the state
let selectedUsers = assessments.filter((obj) => {
// store immutable retrieval of the client user id in a variable called userId
let userId = obj.getIn(["user", "client_user_id"])
// when the user clicks 'Add' user, if the id of the user matches the selected user id
// the user, represented here by obj, is pushed into the selectedUsers array stored in the state.
if(userId === clientUserId){
return obj.setIn(["user", "selected"], true)
}
// If the user id is not equal to the selected user, that team member is kept in the
// current team array represented by the state.
return userId !== clientUserId
})
// update the state with the current representation of the state determined by the user
// selected team members for assessment requests
this.setState({
suggestedUsers: selectedUsers
})
}
我的核心问题是:
我想在调用此函数时将用户对象中 'selected' 键的值更新为 false。
我知道我不能改变我直接过滤的列表,但我已经尝试了多种不同的方法来更新选定的值(即使用 updateIn 和 setIn)。我知道我需要将调用 setIn 的结果设置为一个变量,并将 return 设置为我正在过滤的列表,但我无法在现有列表中获取要更新的值。任何帮助是极大的赞赏。谢谢!
我已经证实,当我手动更改值时,它可以正常工作。如何通过更新此列表将其更改为不可变的。
=========================================== ============================
感谢社区的反馈。过滤和映射确实被证明是矫枉过正的。使用 immutability-helper,我可以在单击的索引处更新特定用户的选定值。一个没有提到的警告是使用合并将更新的数据合并到以前的数据中。在使用不变性助手更新后,我将更新后的值推送到一个数组中,然后将其制成一个列表,并将其合并到我的原始数据中。代码如下:
let users = this.state.teamAssessments
let selectedArray = []
users.map((obj, index) => {
let objId = obj.getIn(["user", "client_user_id"])
if(objId === clientUserId){
const selectedUser = update(this.state.teamAssessments.toJS(), {
[index]: {
user : {
selected: {
$set: true
}
}
}
})
selectedArray.push(selectedUser)
}
})
let updatedArray = fromJS(selectedArray).get(0)
let mergedData = users.merge(updatedArray)
this.setState({
teamAssessments: mergedData
})
你需要immutability-helper。基本上,无需克隆整个对象,只需修改对象的一小部分并在完成后重新设置状态。
import update from 'immutability-helper';
const newData = update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}
});
this.setState({varName: newData});
换句话说,我会在枚举数组时放弃 fromJS 和修改数组。首先,枚举数组并创建更新。然后,单独应用更新。另外,对我来说 "selected" var 似乎是多余的,因为你知道它们是否被选中,因为过滤后的数组名称是 "selectedUsers."
如果我对你的问题的理解正确,我的建议如下:
selectUser(clientUserId) {
let suggestedUsers = this.state.suggestedUsers.map(
userBlock =>
userBlock.setIn(
['user', 'selected'],
userBlock.getIn(['user', 'client_user_id']) === clientUserId
)
);
this.setState({
suggestedUsers,
});
}
确认 - 您只是想修改 state.suggestedUsers
以使 selected
对所选用户为真,对其他人为假?听起来非常适合 Immutable 的 map
函数(而不是 filter
,它只会 return 列表中的元素,您的谓词函数 return 是真实的)。
顺便说一句,您传递给 fromJS
的对象有一个错误——您需要在第一个 assessor_assessment
块之后添加一个额外的 },
。
我有一个不可变列表,如下所示:
this.state = {
suggestedUsers: fromJS([
{
user: {
client_user_id: "1234567890",
full_name: "marty mcfly",
image: "imageURL",
role_name: "Associate Graphic Designer",
selected: false
}
},
{
user: {
client_user_id: "0987654321",
full_name: "doc",
image: "imageURL",
role_name: "Software Engineer",
selected: false
}
}
)]
这用于在 UI 中显示此信息的 div。 当我点击 div 时,我有一个函数被触发,如下所示:
selectUser(clientUserId){
// set assessments variable equal to the current team from the state
let assessments = fromJS(this.state.suggestedUsers)
let selectAssessor
// set a variable called selectedUsers equal to the results of filtering over the current suggestedUsers from the state
let selectedUsers = assessments.filter((obj) => {
// store immutable retrieval of the client user id in a variable called userId
let userId = obj.getIn(["user", "client_user_id"])
// when the user clicks 'Add' user, if the id of the user matches the selected user id
// the user, represented here by obj, is pushed into the selectedUsers array stored in the state.
if(userId === clientUserId){
return obj.setIn(["user", "selected"], true)
}
// If the user id is not equal to the selected user, that team member is kept in the
// current team array represented by the state.
return userId !== clientUserId
})
// update the state with the current representation of the state determined by the user
// selected team members for assessment requests
this.setState({
suggestedUsers: selectedUsers
})
}
我的核心问题是:
我想在调用此函数时将用户对象中 'selected' 键的值更新为 false。
我知道我不能改变我直接过滤的列表,但我已经尝试了多种不同的方法来更新选定的值(即使用 updateIn 和 setIn)。我知道我需要将调用 setIn 的结果设置为一个变量,并将 return 设置为我正在过滤的列表,但我无法在现有列表中获取要更新的值。任何帮助是极大的赞赏。谢谢!
我已经证实,当我手动更改值时,它可以正常工作。如何通过更新此列表将其更改为不可变的。
=========================================== ============================
感谢社区的反馈。过滤和映射确实被证明是矫枉过正的。使用 immutability-helper,我可以在单击的索引处更新特定用户的选定值。一个没有提到的警告是使用合并将更新的数据合并到以前的数据中。在使用不变性助手更新后,我将更新后的值推送到一个数组中,然后将其制成一个列表,并将其合并到我的原始数据中。代码如下:
let users = this.state.teamAssessments
let selectedArray = []
users.map((obj, index) => {
let objId = obj.getIn(["user", "client_user_id"])
if(objId === clientUserId){
const selectedUser = update(this.state.teamAssessments.toJS(), {
[index]: {
user : {
selected: {
$set: true
}
}
}
})
selectedArray.push(selectedUser)
}
})
let updatedArray = fromJS(selectedArray).get(0)
let mergedData = users.merge(updatedArray)
this.setState({
teamAssessments: mergedData
})
你需要immutability-helper。基本上,无需克隆整个对象,只需修改对象的一小部分并在完成后重新设置状态。
import update from 'immutability-helper';
const newData = update(myData, {
x: {y: {z: {$set: 7}}},
a: {b: {$push: [9]}}
});
this.setState({varName: newData});
换句话说,我会在枚举数组时放弃 fromJS 和修改数组。首先,枚举数组并创建更新。然后,单独应用更新。另外,对我来说 "selected" var 似乎是多余的,因为你知道它们是否被选中,因为过滤后的数组名称是 "selectedUsers."
如果我对你的问题的理解正确,我的建议如下:
selectUser(clientUserId) {
let suggestedUsers = this.state.suggestedUsers.map(
userBlock =>
userBlock.setIn(
['user', 'selected'],
userBlock.getIn(['user', 'client_user_id']) === clientUserId
)
);
this.setState({
suggestedUsers,
});
}
确认 - 您只是想修改 state.suggestedUsers
以使 selected
对所选用户为真,对其他人为假?听起来非常适合 Immutable 的 map
函数(而不是 filter
,它只会 return 列表中的元素,您的谓词函数 return 是真实的)。
顺便说一句,您传递给 fromJS
的对象有一个错误——您需要在第一个 assessor_assessment
块之后添加一个额外的 },
。