This article is the tenth of a series of articles explaining the source code of ahoos in simple language, which has been organized into document- address . I think it's not bad, give me a follow to support it, thanks.
Today, let's talk about the hooks for state management of Map and Set types in ahooks, and review the two data types of Set and Map by the way.
useMap
Hook to manage the state of the Map type.
First review the concept of the following Map. Map objects hold key-value pairs and are able to remember the original insertion order of keys . Any value (object or primitive type) can be a key or a value.
Object and Map are very similar. They both allow you to access a value by key, delete a key, and check if a key is bound to a value. So in the past we have always used objects as Maps.
However, in some scenarios, using Map is a better choice. Here are some common points:
- Type of key value. The keys of a Map can be any value, including functions, objects, or any primitive type. An Object key must be a String or Symbol.
- The order of key values needs to be guaranteed. The keys in a Map are ordered. Therefore, when iterating, a Map object returns the keys in the order they were inserted . While Object's keys are currently ordered, this is not always the case, and the ordering is complex. Therefore, it is best not to rely on the order of properties .
- Size. The number of key-value pairs in a Map can be easily obtained through the size property. The number of key-value pairs of Object can only be calculated manually. For example, iterating over object properties and counting its number.
- performance. Map performs better in scenarios where key-value pairs are frequently added or deleted . Object is not optimized in scenarios where key-value pairs are frequently added and deleted.
For more, see the comparison of Objects and maps .
Let's take a look at what encapsulation ahooks has done, and review some basic API usages of the following Map.
The first is to set the default value, and create a Map object through the Map constructor new Map()
. The input parameter is the default value.
function useMap<K, T>(
// 传入默认的 Map 参数
initialValue?: Iterable<readonly [K, T]>,
) {
const getInitValue = () => {
return initialValue === undefined ? new Map() : new Map(initialValue);
};
const [map, setMap] = useState<Map<K, T>>(() => getInitValue());
// 省略代码...
}
set method. Add new key and value of Map or update the value of key, because React is immutable data and needs to return a new value, so you need to create a new Map object.
Set the value associated with the specified key key in the Map object through the set method of Map, and return the Map object.
// 添加 map
const set = (key: K, entry: T) => {
setMap((prev) => {
const temp = new Map(prev);
temp.set(key, entry);
return temp;
});
};
remove method. Remove the specified key-value pair in the Map object through the delete method of the Map. If the key-value pair exists and is successfully removed, it returns true, otherwise it returns false. Calling Map.prototype.has(key) after calling delete will return false.
// 移除
const remove = (key: K) => {
setMap((prev) => {
const temp = new Map(prev);
temp.delete(key);
return temp;
});
};
- setAll method. Pass in a brand new Map object, directly overwriting the old Map object.
- reset method. Reset the Map object to its initial value. There is a clear method in Map, which removes all key-value pairs in the Map object . Compared with clear, the reset method is closer to our needs.
- The get method, through the get method of Map, returns the value associated with the key , or returns undefined if there is no associated value.
// 生成一个新的 Map 对象
const setAll = (newMap: Iterable<readonly [K, T]>) => {
setMap(new Map(newMap));
};
// 重置
const reset = () => setMap(getInitValue());
// 获取
const get = (key: K) => map.get(key);
For some other methods without side effects, ahoos is not encapsulated, which I think is reasonable. When developers want to use these methods, they can be called directly.
- has(key). Returns a boolean value indicating whether the value associated with key exists in the Map object .
- keys(). Returns a new iterator object containing all the keys in the Map object, in the order in which the Map object was inserted .
- values(). Returns a new iterator object containing all the values in the Map object, in the order they were inserted into the Map object .
- entries(). Returns a new iterator object that is a [key, value] array containing all key-value pairs in the Map object, in the order in which the Map objects were inserted .
useSet
A Hook that manages the state of a Set type.
Just look at the code.
To set the default value , create a new Set object through the new Set() constructor .
function useSet<K>(initialValue?: Iterable<K>) {
const getInitValue = () => {
return initialValue === undefined ? new Set<K>() : new Set(initialValue);
};
const [set, setSet] = useState<Set<K>>(() => getInitValue());
// 省略一些代码
}
The add method adds an element. Call the add method of Set to add an element to the end of the Set object . Returns this Set object.
const add = (key: K) => {
if (set.has(key)) {
return;
}
setSet((prevSet) => {
const temp = new Set(prevSet);
temp.add(key);
return temp;
});
};
The remove method removes an element. Call the delete(value) method of Set to remove the element in the Set that is equal to this value , and return the value that Set.prototype.has(value) would have returned before this operation (that is, if the element exists, return true, otherwise return false ). Set.prototype.has(value) will return false after this.
// 移除
const remove = (key: K) => {
if (!set.has(key)) {
return;
}
setSet((prevSet) => {
const temp = new Set(prevSet);
temp.delete(key);
return temp;
});
};
The reset method resets the Set back to the default value. The corresponding clear method of Set will remove all elements in the Set object .
// 重置
const reset = () => setSet(getInitValue());
Other Set methods:
- entries(). Returns a new iterator object containing the [value, value] array of the values of all elements in the Set object in insertion order . To keep this method similar to a Map object, the key and value of each value are equal.
- has(value). Returns a boolean value indicating whether the value exists in the Set.
- keys() and values(). Both return a new iterator object containing the values of all elements in the Set object in insertion order.
- forEach(callbackFn[, thisArg]). CallBackFn is called once for each value in the Set object, in insertion order. If the thisArg parameter is provided, this in the callback will be this parameter .
Thinking and Summarizing
The two data structures of Map and Set in ES6 make up for some deficiencies before JavaScript, such as Object objects can only be of type string or Symbol. In addition, it provides a more convenient operation method in some cases, such as array deduplication, we can directly new Set([...arr])
.
Now more and more scenarios use Map and Set, ahooks encapsulates both of them is relatively simple, and more is the encapsulation of some operations with side effects (modification to the original Map and Set). Look at the source code of this part, just as a little review of the basics.
This article has been included in the personal blog , welcome to pay attention~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。