From 6388dd98fe186c782fbf7e553fb91db0f908b215 Mon Sep 17 00:00:00 2001 From: zombiej Date: Mon, 18 Jan 2021 15:36:35 +0800 Subject: [PATCH 1/2] refactor: opt form cache speed --- src/utils/NameMap.ts | 51 ++++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 18 deletions(-) diff --git a/src/utils/NameMap.ts b/src/utils/NameMap.ts index d96b8cc5..b4259dd4 100644 --- a/src/utils/NameMap.ts +++ b/src/utils/NameMap.ts @@ -1,32 +1,36 @@ -import { InternalNamePath } from '../interface'; -import { matchNamePath } from './valueUtil'; +import type { InternalNamePath } from '../interface'; interface KV { key: InternalNamePath; value: T; } +const SPLIT = '__@field_split__'; + +/** + * Convert name path into string to fast the fetch speed of Map. + */ +function normalize(namePath: InternalNamePath): string { + return ( + namePath + .map(cell => `${typeof cell}:${cell}`) + // Magic split + .join(SPLIT) + ); +} + /** * NameMap like a `Map` but accepts `string[]` as key. */ class NameMap { - private list: KV[] = []; + private kvs = new Map(); public set(key: InternalNamePath, value: T) { - const index = this.list.findIndex(item => matchNamePath(item.key, key)); - if (index !== -1) { - this.list[index].value = value; - } else { - this.list.push({ - key, - value, - }); - } + this.kvs.set(normalize(key), value); } public get(key: InternalNamePath) { - const result = this.list.find(item => matchNamePath(item.key, key)); - return result && result.value; + return this.kvs.get(normalize(key)); } public update(key: InternalNamePath, updater: (origin: T) => T | null) { @@ -41,15 +45,26 @@ class NameMap { } public delete(key: InternalNamePath) { - this.list = this.list.filter(item => !matchNamePath(item.key, key)); + this.kvs.delete(normalize(key)); } + // Since we only use this in test, let simply realize this public map(callback: (kv: KV) => U) { - return this.list.map(callback); + return [...this.kvs.entries()].map(([key, value]) => { + const cells = key.split(SPLIT); + + return callback({ + key: cells.map(cell => { + const [, type, unit] = cell.match(/^([^:]*):(.*)$/); + return type === 'number' ? Number(unit) : unit; + }), + value, + }); + }); } - public toJSON(): { [name: string]: T } { - const json: { [name: string]: T } = {}; + public toJSON(): Record { + const json: Record = {}; this.map(({ key, value }) => { json[key.join('.')] = value; return null; From 6644f706c4660ee0d3bae56f2fa65bbefb9aa0be Mon Sep 17 00:00:00 2001 From: zombiej Date: Mon, 18 Jan 2021 15:37:36 +0800 Subject: [PATCH 2/2] fix: lint --- .eslintrc.js | 1 + src/useForm.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.eslintrc.js b/.eslintrc.js index 2ae6fb00..aeb51e41 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -18,5 +18,6 @@ module.exports = { '@typescript-eslint/no-redeclare': 0, '@typescript-eslint/method-signature-style': 0, 'no-async-promise-executor': 0, + '@typescript-eslint/consistent-type-definitions': 0, }, }; diff --git a/src/useForm.ts b/src/useForm.ts index baa5d8e0..ca5e8f8a 100644 --- a/src/useForm.ts +++ b/src/useForm.ts @@ -1,6 +1,6 @@ import * as React from 'react'; import warning from 'rc-util/lib/warning'; -import { +import type { Callbacks, FieldData, FieldEntity,