[英]How can I make my filtering and mapping of arrays more compact and less repetitive?
所以我有一个对象数组,我 map 并根据设置的过滤选项显示。
这是示例数组:
[ { "id": 1, "class": "Assault Infantry", "missions": 5, "shots": 28, "hits": 21, "kills": 22, "dead": true, }, { "id": 2, "class": "Field Medic", "missions": 5, "shots": 22, "hits": 17, "kills": 15, "dead": false, }, { "id": 3, "class": "Field Medic", "missions": 3, "shots": 15, "hits": 11, "kills": 8, "dead": true, }, { "id": 4, "class": "Skirmisher", "missions": 7, "shots": 38, "hits": 27, "kills": 25, "dead": false, }, { "id": 5, "class": "Phalanx", "missions": 2, "shots": 5, "hits": 3, "kills": 5, "dead": true, }, { "id": 6, "missions": 6, "shots": 50, "hits": 41, "kills": 31, "dead": false, }, { "id": 7, "class": "Rookie", "missions": 1, "shots": 2, "hits": 1, "kills": 1, "dead": true, },
然后我有 select 特定字段的选择器,并使用 state 按所选值对 arrays 进行排序:
const [data, setData] = useState([]);
const [sortType, setSortType] = useState('kills');
<select onChange={(e) => setSortType(e.target.value)}>
<option value="kills">Kills</option>
<option value="shots">Shots</option>
<option value="missions">Missions</option>
<option value="accuracy">Accuracy</option>
</select>
下面有一个复选框,如果选中,则进一步过滤排序数组并删除特定实例:
const [isChecked, setIsChecked] = useState(false);
const handleOnChange = () => {
setIsChecked(!isChecked);
};
<input onChange={handleOnChange} type="checkbox" id="isDead" name="isDead" checked={isChecked} />
<label htmlFor="isDead">Hide Dead</label>
这是执行大部分排序和过滤的代码,目前它按预期工作,我很高兴它是如何工作的:
useEffect(() => {
const sortArray = type => {
const types = {
mvps: 'mvps',
kills: 'kills',
shots: 'shots',
missions: 'missions',
};
const sortProperty = types[type];
if(sortType === "accuracy") {
if(isChecked) {
console.log(isChecked);
const sorted = data.filter((user) => user.dead !== true);
console.log(sorted);
setData(sorted);
filtered(sorted);
} else {
const sorted = [...soldiers].sort((a, b) => (b.hits / b.shots * 100) - (a.hits / a.shots * 100));
setData(sorted);
filtered(sorted);
}
} else {
if(isChecked) {
const sorted = data.filter((user) => user.dead !== true);
console.log(sorted);
setData(sorted);
filtered(sorted);
} else {
const sorted = [...soldiers].sort((a, b) => b[sortProperty] - a[sortProperty]);
setData(sorted);
filtered(sorted);
}
}
};
sortArray(sortType);
}, [sortType, isChecked]);
它基本上采用选择器的值并根据所选值的类型对数组进行排序,如果选中“isDead”复选框,它会过滤数组并删除将“dead”设置为 true 的实例。 但是,我的问题是我不断重复代码,如果选中它们,我想添加更多复选框以通过更多选项过滤数组,如果我想这样做,它当前的设置方式将意味着我会用不同的值一遍又一遍地重复相同的代码。 如果我想添加更多复选框选项来过滤 arrays(例如使用“类”值),如何使代码的可重复性降低? 例如,有多个复选框来显示“野战医生”、“突击步兵”等。
我认为这里的关键问题是,通过您的方法,您需要在if
分支中声明sorted
,这就是为什么您需要所有重复的setData(sorted)
等。
因此解决方案是在条件之外的 scope 中sorted
以使其可用,但仍适用条件。
有不同的可能方法。
(我的示例并未反映您的确切用例,但我想它们说明了这个想法,从那里开始就会很容易。)
例如,将条件提取到单独的 function 中:
const getSorted = function( sortType, isChecked ){
if(sortType === "accuracy") {
// ...
return data.filter((user) => user.dead !== true);
} else {
// ...
}
};
useEffect(() => {
// ...
const sorted = getSorted( sortType, isChecked ); // <-- all the if-conditions are in here
setData( sorted );
filtered( sorted );
// ...
}
另一种方法是定义一个 object 来指定sortType
的一些属性,例如条件、修饰符……例如:
const sortTypesSpec = {
'accuracy': {
sortFunction: (a, b) => b[sortProperty] - a[sortProperty],
filterFunction: (user) => user.dead !== true,
// ... other properties ?
},
'default': {
// ...
}
};
useEffect(() => {
// ...
const sorted = isChecked
? data.filter( sortTypesSpec[ sortType ].filterFunction )
: [...soldiers].sort( sortTypesSpec[ sortType ].sortFunction );
setData( sorted );
filtered( sorted );
// ...
当然,您也可以将其提取到 function 中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.