React flatten state 的使用
使用flatten state(数据扁平化)通过将数据结构转换为对象形式,以唯一标识符作为键,可以显著提高在React中对大数据集的操作效率和代码清晰度。
什么是flatten state?
flatten state目的是就是把数据扁平化,更加方便我们对数据的操作,flatten就是类似于使用HashMap的形式,在JavaScript中我们可以使用Object。
实际使用
在这里我们以React为例子,在ReactHooks
中我们经常对数据进行操作,但是如果操作的是一个对象数组并且该数组非常大这样时很耗时的,代码也很冗余,所以我们可以考虑把数组转化成为flattenState的形式。
const initState = [
{id: 1, name: 'RMA', champion: 13},
{id: 2, name: 'ACM', champion: 7},
{id: 3, name: 'MUN', champion: 4},
{id: 4, name: 'ARS', champion: 0}
]
const [teams, setTeams] = useState()
对于这样的数据如果我们需要查找某一个数据或者修改某一个数据时对应的时间复杂度为O(n)
,因为我们每次对数据进行操作都需要循环遍历一次数组。
// 删除一项
const deleteData = (id) => {
return teams.filter(item => item.id !== id)
}
const newTeams = deleteData(3)
setTeams(newTeams)
// 修改一项
const modifyData = (id, val) => {
return teams.map(item => {
if(item.id === id) { // tips:item为引用值可以改变
item.champion = val
}
return item
})
}
const newData = modifyData(4, 1)
setTeams(newData)
// 查找一项
const findData = (id) => {
return teams.find(item => item.id === id)
}
在我们熟悉使用数组的一些高阶方法之后操作起来还是比较方便的,但是如果数据量过大每次循环还是很耗时的。有没有更好的方法呢?当然就是使用flattenState
(Object
)来解决。
3、使用hashMap的形式
上面的数据有一个特点就是每一个数据项都具体有唯一的标识符(id
),在上面的例子中我们在查找某一个数据项的时候使用的该唯一标识符。
查找某个特定的数据的时候不需要再通过循环遍历每一项然后使用每一项的id
和特定id
对比,可以直接访问id就能够访问到其对应的数据不需要再使用循环了,能够做到这样能力就是对象(object
)。
所以我们需要将上面的形式转化为下面这样的
const flattenState = {
1: {id: 1, name: 'RMA', champion: 13},
2: {id: 2, name: 'ACM', champion: 7},
3: {id: 3, name: 'MUN', champion: 4},
4: {id: 4, name: 'ARS', champion: 0}
}
上面这一种形式就是使用唯一的id
来作为键值对的键来方便数据的操作,把上面数组的某一项作为键值对的值。
对数据操作
// 删除
const deleteData = (id) => {
delete flattenState[id]
setTeams(flattenState)
}
// 修改id为'1'的
const modifyData = (id, val) => {
const newTeam = {...Teams[id], champion: val}
setTeams({...teams, [id]: newTeam})
}
// 查询
const findData = (id) => {
return teams[id]
}
这样就方便许多了,我们在操作数据的时候就不需要循环了所以时间复杂度变味了O(1)
,思路也更加清晰了,代码也没有以前那么多了。
4、数组形式flattenState形式相互转化
数组转化为flattenState
const converseArrToObj = (arr) => {
return arr.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
}
flattenState转化为数组
const converseObjToArr = (obj) => {
const keys = Object.keys(obj)
return keys.map(key => {
return obj[key]
})
}