在设置状态 React JS 之前检查对象数组是否存在于对象数组中的简单方法
Easy way to check if array of objects exists in array of objects before setting state React JS
考虑以下因素:
this.setState({
validations: [...this.state.validations, ...validations]
}, () => {
// ... Do something
});
我在做什么:[...this.state.validations, ...validations]
validations 是一个对象数组。
例如:
// validation
[{message: 'hello', isError: true, fieldId: 87}, ....]
基本上每次我们遇到验证错误时,我们都会将一个对象数组设置为一个数组,如上所示。
问题是有时会添加重复的对象。重复我的意思是在消息部分,所以 this.state.validations
看起来像:
[
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 87},
...
]
我想做的是根据 validations
中的消息和 fieldId 过滤 this.state.validations
并说:
// If this message doesn't exist for this field id, set it.
有没有一种简单的方法可以做到这一点,我可以使用过滤器或其他东西来循环状态验证和比较 fieldId 和消息的验证,如果它不存在:添加它?
您可以使用 Array.find() 验证每个验证是否已存在,如果不存在则仅添加到状态验证。
var stateValidations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 42},
{message: 'error', isError: true, fieldId: 95},
];
var validations = [
{message: 'hello', isError: true, fieldId: 42}, // Already exists.
{message: 'hello', isError: true, fieldId: 101} // New item.
];
// Check if each validation already exists, and only add if doesn't exist.
validations.forEach(validation => {
const found = stateValidations.find(item => item.message === validation.message
&& item.fieldId === validation.fieldId);
if (!found) {
// If not found, add validation.
stateValidations.push(validation);
}
});
console.log(JSON.stringify(stateValidations));
将验证结构化为对象而不是数组的更好方法之一
例如
validations: {
[fieldId1]: [{ message: 'hello', isError: true }, { message: 'bye', isError: true}],
[fieldId2]: [{ message: 'hello', isError: true }],
}
通过这种结构,您可以通过一个字段 Id 清楚地看到所有验证都存在。
现在要查明是否已对 fieldId 进行验证,您可以执行以下操作:
if (validations[fieldId].filter(v => v.message === 'your message').length === 0) {
this.setState({
validations: {
...validations,
[fieldId]: [...validations[fieldId], { message: 'your message', isError: true }]
}
})
}
通过这种方式,当你需要读取特定字段Id上的所有验证时,你可以直接说:
this.state.validations[fieldId]
而不是再次根据 fieldId 过滤数组。
您可以从现有的状态验证数组中创建 Set
of "keys",其中每个键都是 message|fieldId
形式的字符串。然后,您可以根据新验证消息的键是否存在于先前创建的集合中,通过过滤掉 validations
中的元素来创建新数组:
const stateValidations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'world', isError: true, fieldId: 87},
{message: 'hi', isError: true, fieldId: 88}
];
const validations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'there', isError: true, fieldId: 88}
];
const messageKey = ({message, fieldId}) => `${message}|${fieldId}`;
const existing = new Set(stateValidations.map(messageKey));
const res = [...stateValidations, ...validations.filter(v => !existing.has(messageKey(v)))];
console.log(res);
嗯,首先我们需要解决一些问题。 setState 是异步的,因此调用 setState 并传入一个取决于先前状态的值是一个潜在的陷阱。
所以不要这样做:
this.setState({ value: ...this.state.value });
我们需要将 setState 与更新函数一起使用,如下所示:
this.setState(prevState => ({ value: ...prevState.value }));
接下来,让我们通过过滤新验证来解决您的问题,方法是在 prevState.validations.
中找到匹配项
this.setState(prevState => {
let toAdd = validations.filter(
item =>
undefined ===
prevState.validations.find(
prevItem => item.message === prevItem.message && item.fieldId === prevItem.fieldId
)
);
return [...prevState.validations, ...toAdd];
});
解决方案非常简单,
- 找到使项目独一无二的原因
- 遍历现有项目,如果不重复则添加。如果重复使用新项目并缩短新数组以提高性能
- 添加所有剩余项目
const stateValidations = [
{message: 'hello', isError: true, fieldId: 85},
{message: 'world', isError: true, fieldId: 86},
{message: 'hi', isError: true, fieldId: 88}
];
const validations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'there', isError: true, fieldId: 88}
];
let newValidations = stateValidations.reduce((acc, curr)=>{
let haveNewvalidation = validations.findIndex((v)=>v.fieldId===curr.fieldId);
if(haveNewvalidation !=-1){
acc.push(validations[haveNewvalidation]);
// this will improve findIndex performance
validations.splice(haveNewvalidation,1);
} else {
acc.push(curr);
}
return acc;
}, [])
// push remaining validations
newValidations.push(...validations)
console.log(newValidations)```
Demo: https://repl.it/@abhirathore2006/mergeTwoArrays
考虑以下因素:
this.setState({
validations: [...this.state.validations, ...validations]
}, () => {
// ... Do something
});
我在做什么:[...this.state.validations, ...validations]
validations 是一个对象数组。
例如:
// validation
[{message: 'hello', isError: true, fieldId: 87}, ....]
基本上每次我们遇到验证错误时,我们都会将一个对象数组设置为一个数组,如上所示。
问题是有时会添加重复的对象。重复我的意思是在消息部分,所以 this.state.validations
看起来像:
[
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 87},
...
]
我想做的是根据 validations
中的消息和 fieldId 过滤 this.state.validations
并说:
// If this message doesn't exist for this field id, set it.
有没有一种简单的方法可以做到这一点,我可以使用过滤器或其他东西来循环状态验证和比较 fieldId 和消息的验证,如果它不存在:添加它?
您可以使用 Array.find() 验证每个验证是否已存在,如果不存在则仅添加到状态验证。
var stateValidations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'hello', isError: true, fieldId: 42},
{message: 'error', isError: true, fieldId: 95},
];
var validations = [
{message: 'hello', isError: true, fieldId: 42}, // Already exists.
{message: 'hello', isError: true, fieldId: 101} // New item.
];
// Check if each validation already exists, and only add if doesn't exist.
validations.forEach(validation => {
const found = stateValidations.find(item => item.message === validation.message
&& item.fieldId === validation.fieldId);
if (!found) {
// If not found, add validation.
stateValidations.push(validation);
}
});
console.log(JSON.stringify(stateValidations));
将验证结构化为对象而不是数组的更好方法之一
例如
validations: {
[fieldId1]: [{ message: 'hello', isError: true }, { message: 'bye', isError: true}],
[fieldId2]: [{ message: 'hello', isError: true }],
}
通过这种结构,您可以通过一个字段 Id 清楚地看到所有验证都存在。
现在要查明是否已对 fieldId 进行验证,您可以执行以下操作:
if (validations[fieldId].filter(v => v.message === 'your message').length === 0) {
this.setState({
validations: {
...validations,
[fieldId]: [...validations[fieldId], { message: 'your message', isError: true }]
}
})
}
通过这种方式,当你需要读取特定字段Id上的所有验证时,你可以直接说:
this.state.validations[fieldId]
而不是再次根据 fieldId 过滤数组。
您可以从现有的状态验证数组中创建 Set
of "keys",其中每个键都是 message|fieldId
形式的字符串。然后,您可以根据新验证消息的键是否存在于先前创建的集合中,通过过滤掉 validations
中的元素来创建新数组:
const stateValidations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'world', isError: true, fieldId: 87},
{message: 'hi', isError: true, fieldId: 88}
];
const validations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'there', isError: true, fieldId: 88}
];
const messageKey = ({message, fieldId}) => `${message}|${fieldId}`;
const existing = new Set(stateValidations.map(messageKey));
const res = [...stateValidations, ...validations.filter(v => !existing.has(messageKey(v)))];
console.log(res);
嗯,首先我们需要解决一些问题。 setState 是异步的,因此调用 setState 并传入一个取决于先前状态的值是一个潜在的陷阱。
所以不要这样做:
this.setState({ value: ...this.state.value });
我们需要将 setState 与更新函数一起使用,如下所示:
this.setState(prevState => ({ value: ...prevState.value }));
接下来,让我们通过过滤新验证来解决您的问题,方法是在 prevState.validations.
中找到匹配项 this.setState(prevState => {
let toAdd = validations.filter(
item =>
undefined ===
prevState.validations.find(
prevItem => item.message === prevItem.message && item.fieldId === prevItem.fieldId
)
);
return [...prevState.validations, ...toAdd];
});
解决方案非常简单,
- 找到使项目独一无二的原因
- 遍历现有项目,如果不重复则添加。如果重复使用新项目并缩短新数组以提高性能
- 添加所有剩余项目
const stateValidations = [
{message: 'hello', isError: true, fieldId: 85},
{message: 'world', isError: true, fieldId: 86},
{message: 'hi', isError: true, fieldId: 88}
];
const validations = [
{message: 'hello', isError: true, fieldId: 87},
{message: 'there', isError: true, fieldId: 88}
];
let newValidations = stateValidations.reduce((acc, curr)=>{
let haveNewvalidation = validations.findIndex((v)=>v.fieldId===curr.fieldId);
if(haveNewvalidation !=-1){
acc.push(validations[haveNewvalidation]);
// this will improve findIndex performance
validations.splice(haveNewvalidation,1);
} else {
acc.push(curr);
}
return acc;
}, [])
// push remaining validations
newValidations.push(...validations)
console.log(newValidations)```
Demo: https://repl.it/@abhirathore2006/mergeTwoArrays