Skip to content

Commit

Permalink
perf: replace get with toValue
Browse files Browse the repository at this point in the history
  • Loading branch information
EdieLemoine committed Jan 25, 2024
1 parent 84ed058 commit 2185f6f
Show file tree
Hide file tree
Showing 12 changed files with 74 additions and 80 deletions.
9 changes: 4 additions & 5 deletions apps/demo/src/forms/shipmentOptionsForm.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
/* eslint-disable @typescript-eslint/no-magic-numbers */
import {ref} from 'vue';
import {get} from '@vueuse/core';
import {ref, toValue} from 'vue';
import {defineField, defineForm, type InteractiveElementInstance} from '@myparcel/vue-form-builder/ts';
import {isOfType} from '@myparcel/ts-utils';
import {type CarrierName, PACKAGE_TYPE_IDS_TO_NAMES, PackageTypeName} from '@myparcel/constants';
Expand All @@ -18,7 +17,7 @@ import FormGroup from '../components/template/FormGroup.vue';
import Heading from '../components/Heading.vue';
import Bonnetje from '../components/Bonnetje.vue';

// eslint-disable-next-line id-length
// eslint-disable-next-line id-length,@typescript-eslint/consistent-type-imports
declare const h: typeof import('vue').h;

const firstName = ref('');
Expand All @@ -33,7 +32,7 @@ const validateName = <Type = unknown,>(field: InteractiveElementInstance<Type>)
return;
}

nameField.props.errors = [...(get(firstNameField?.errors) ?? []), ...(get(lastNameField?.errors) ?? [])];
nameField.props.errors = [...(toValue(firstNameField?.errors) ?? []), ...(toValue(lastNameField?.errors) ?? [])];
};

export const shipmentOptionsForm = defineForm('shipmentOptions', {
Expand Down Expand Up @@ -345,7 +344,7 @@ export const shipmentOptionsForm = defineForm('shipmentOptions', {
visibleWhen: ({form}: InteractiveElementInstance) => {
const {packageType, carrier} = form.model;

return packageType.ref.value === PackageTypeName.Package && ['dhlforyou'].includes(get(carrier.ref));
return packageType.ref.value === PackageTypeName.Package && ['dhlforyou'].includes(toValue(carrier.ref));
},
}),

Expand Down
7 changes: 3 additions & 4 deletions apps/demo/src/views/ShipmentOptionsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,15 @@
</template>

<script lang="ts" setup>
import {computed, ref, watch} from 'vue';
import {get} from '@vueuse/core';
import {computed, ref, watch, toValue} from 'vue';
import {type FormInstance} from '@myparcel-vfb/core';
import {MagicForm} from '@myparcel/vue-form-builder/ts';
import {shipmentOptionsForm} from '../forms/shipmentOptionsForm';
import FormDiagnostics from '../components/FormDiagnostics.vue';
const formClasses = ref<string[]>([]);
const dirty = computed(() => get(shipmentOptionsForm.isDirty));
const dirty = computed(() => toValue(shipmentOptionsForm.isDirty));
// Ask an user to confirm leaving the page when the form is dirty
// TODO: Should this be a built-in option?
Expand All @@ -45,6 +44,6 @@ watch(dirty, (isDirty) => {
});
const afterValidate = (form: FormInstance) => {
formClasses.value = get(form.isValid) ? ['border-green-500'] : ['border-red-500'];
formClasses.value = toValue(form.isValid) ? ['border-green-500'] : ['border-red-500'];
};
</script>
7 changes: 3 additions & 4 deletions libs/core/src/__tests__/form/field.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {h, markRaw, ref, nextTick} from 'vue';
import {h, markRaw, ref, nextTick, toValue} from 'vue';
import {describe, expect, it, vi} from 'vitest';
import {get} from '@vueuse/core';
import {flushPromises, mount} from '@vue/test-utils';
import {generateForm, optionData} from '../utils';
import {firstNameNotDuane} from '../examples/validators';
Expand Down Expand Up @@ -186,8 +185,8 @@ describe('Form fields', () => {
initialValues: {element: 'hello', toggle: false},
});

expect(get(form.model.element.ref)).toBe('hello');
expect(get(form.model.toggle.ref)).toBe(false);
expect(toValue(form.model.element.ref)).toBe('hello');
expect(toValue(form.model.toggle.ref)).toBe(false);
});

it.skip('can pass through slots', async () => {
Expand Down
17 changes: 8 additions & 9 deletions libs/core/src/__tests__/form/formInstance.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import {ref} from 'vue';
import {ref, toValue} from 'vue';
import {describe, expect, it} from 'vitest';
import {get} from '@vueuse/core';
import {flushPromises} from '@vue/test-utils';
import {generateForm} from '../utils';
import TextInput from '../elements/TextInput.vue';
Expand Down Expand Up @@ -144,18 +143,18 @@ describe('Form instance', () => {
it('is false when the form is not dirty', () => {
const form = generateForm(createFormConfig());

expect(get(form.isDirty)).toBe(false);
expect(toValue(form.isDirty)).toBe(false);
});

it('is true when the form is dirty', async () => {
expect.assertions(2);
const form = generateForm(createFormConfig());

expect(get(form.isDirty)).toBe(false);
expect(toValue(form.isDirty)).toBe(false);

form.model.named.ref.value = 'changed';
await flushPromises();
expect(get(form.isDirty)).toBe(true);
expect(toValue(form.isDirty)).toBe(true);
});

it.todo('reverts to false when the form is submitted', async () => {
Expand All @@ -164,10 +163,10 @@ describe('Form instance', () => {

form.model.named.ref.value = 'changed';
await flushPromises();
expect(get(form.isDirty)).toBe(true);
expect(toValue(form.isDirty)).toBe(true);

await form.submit();
expect(get(form.isDirty)).toBe(false);
expect(toValue(form.isDirty)).toBe(false);
});

it.todo('reverts to false when the form is reset', async () => {
Expand All @@ -176,10 +175,10 @@ describe('Form instance', () => {

form.model.named.ref.value = 'changed';
await flushPromises();
expect(get(form.isDirty)).toBe(true);
expect(toValue(form.isDirty)).toBe(true);

await form.reset();
expect(get(form.isDirty)).toBe(false);
expect(toValue(form.isDirty)).toBe(false);
});
});
});
5 changes: 2 additions & 3 deletions libs/core/src/components/MagicForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
</template>

<script generic="V extends FormValues = FormValues" lang="ts" setup>
import {onMounted, provide, ref, toRefs} from 'vue';
import {get} from '@vueuse/core';
import {onMounted, provide, ref, toRefs, toValue} from 'vue';
import {type FormInstance, type FormValues, type FormHooks} from '../types';
import {INJECT_FORM} from '../symbols';
import {FORM_HOOKS, type FormHook} from '../data';
Expand All @@ -42,7 +41,7 @@ const propRefs = toRefs(props);
const propsForm = propRefs.form.value;
onMounted(() => {
const value = get(formElement);
const value = toValue(formElement);
if (!value) {
return;
Expand Down
7 changes: 3 additions & 4 deletions libs/core/src/components/RenderedFormContent.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,7 @@
</template>

<script lang="ts" setup>
import {computed, ref} from 'vue';
import {get} from '@vueuse/core';
import {computed, ref, toValue} from 'vue';
import {useForm} from '../composables';
import FormElementWrapper from './FormElementWrapper';
Expand All @@ -36,6 +35,6 @@ if (!form) {
throw new Error('Form not found');
}
const plainFields = computed(() => get(form.fields).filter((element) => !element.teleportSelector));
const teleportFields = computed(() => get(form.fields).filter((element) => Boolean(element.teleportSelector)));
const plainFields = computed(() => toValue(form.fields).filter((element) => !element.teleportSelector));
const teleportFields = computed(() => toValue(form.fields).filter((element) => Boolean(element.teleportSelector)));
</script>
11 changes: 5 additions & 6 deletions libs/core/src/composables/useFormBuilder.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {type Ref, ref} from 'vue';
import {get} from '@vueuse/core';
import {type Ref, ref, toValue} from 'vue';
import {HookManager} from '@myparcel-vfb/hook-manager';
import {markComponentAsRaw} from '../utils';
import {
Expand Down Expand Up @@ -41,24 +40,24 @@ export const useFormBuilder = (): FormBuilder => {
},

getForm(name) {
return get(forms)[name];
return toValue(forms)[name];
},

// @ts-expect-error todo
register(name, config) {
void hookManager.execute('beforeRegister');
const instance = new Form(name, mergeDefaults(get(defaults), config as FormConfiguration));
const instance = new Form(name, mergeDefaults(toValue(defaults), config as FormConfiguration));

// @ts-expect-error todo
get(forms)[name] = instance;
toValue(forms)[name] = instance;

void hookManager.execute('afterRegister', instance);

return instance;
},

setDefaults(options) {
defaults.value = mergeDefaults(get(defaults), options);
defaults.value = mergeDefaults(toValue(defaults), options);
},
};
};
Expand Down
36 changes: 19 additions & 17 deletions libs/core/src/form/Form.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {computed, ref, watch, reactive, unref} from 'vue';
import {get, isDefined, useMemoize} from '@vueuse/core';
import {computed, ref, watch, reactive, unref, toValue} from 'vue';
import {isDefined, useMemoize} from '@vueuse/core';
import {createHookManager} from '@myparcel-vfb/hook-manager';
import {isOfType} from '@myparcel/ts-utils';
import {markComponentAsRaw} from '../utils';
Expand Down Expand Up @@ -35,7 +35,7 @@ export class Form<V extends FormValues = FormValues> {
public readonly values: FormInstance<V>['values'];

private getFieldMemoized = useMemoize((name: string): AnyElementInstance | null => {
const found = get(this.fields).find((field) => field.name === name);
const found = toValue(this.fields).find((field) => field.name === name);

return found ?? null;
});
Expand All @@ -59,18 +59,18 @@ export class Form<V extends FormValues = FormValues> {
fields.forEach((field) => {
const instance = this.createFieldInstance(field as AnyElementConfiguration, this as unknown as FormInstance<V>);

get(this.fields).push(instance);
toValue(this.fields).push(instance);
});

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
this.interactiveFields = computed(() => {
return get(this.fields).filter((field) => {
return toValue(this.fields).filter((field) => {
return isOfType<InteractiveElementInstance>(field, 'ref');
});
});

this.isDirty = computed(() => get(this.interactiveFields).some((field) => get(field.isDirty)));
this.isDirty = computed(() => toValue(this.interactiveFields).some((field) => toValue(field.isDirty)));

this.stable.value = true;
}
Expand All @@ -84,7 +84,9 @@ export class Form<V extends FormValues = FormValues> {
position: 'before' | 'after' = 'after',
): Promise<S extends string ? undefined | AnyElementInstance : AnyElementInstance> {
await this.hooks.execute(FormHook.BeforeAddElement, this, element);
const newIndex = sibling ? get(this.fields).findIndex((field) => field.name === sibling) : get(this.fields).length;
const newIndex = sibling
? toValue(this.fields).findIndex((field) => field.name === sibling)
: toValue(this.fields).length;

if (sibling && newIndex === -1) {
// eslint-disable-next-line no-console
Expand All @@ -96,7 +98,7 @@ export class Form<V extends FormValues = FormValues> {

const newElement = this.createFieldInstance(element, this as unknown as FormInstance<V>);

get(this.fields).splice(index, 0, newElement);
toValue(this.fields).splice(index, 0, newElement);
await this.hooks.execute(FormHook.AfterAddElement, this, element);

return newElement;
Expand All @@ -109,23 +111,23 @@ export class Form<V extends FormValues = FormValues> {
public getValue<T = unknown>(fieldName: string): T {
const fieldInstance = this.ensureGetField<InteractiveElementInstance>(fieldName);

return get(fieldInstance.ref) as T;
return toValue(fieldInstance.ref) as T;
}

public getValues(): V {
return get(this.values) as V;
return toValue(this.values) as V;
}

public removeElement(name: string): void {
const index = get(this.fields).findIndex((field) => field.name === name);
const index = toValue(this.fields).findIndex((field) => field.name === name);

get(this.fields).splice(index, 1);
toValue(this.fields).splice(index, 1);
this.getFieldMemoized.delete(name);
}

public async reset(): Promise<void> {
await this.hooks.execute(FormHook.BeforeReset, this);
await Promise.all(get(this.interactiveFields).map((field) => field.reset()));
await Promise.all(toValue(this.interactiveFields).map((field) => field.reset()));
await this.hooks.execute(FormHook.AfterReset, this);
}

Expand Down Expand Up @@ -153,7 +155,7 @@ export class Form<V extends FormValues = FormValues> {
await this.hooks.execute(FormHook.BeforeValidate, this);

const result = await Promise.all(
get(this.fields).map((field) => {
toValue(this.fields).map((field) => {
if (!isOfType<InteractiveElementInstance>(field, 'ref')) {
field.resetValidation();
return true;
Expand All @@ -167,7 +169,7 @@ export class Form<V extends FormValues = FormValues> {

await this.hooks.execute(FormHook.AfterValidate, this);

return get(this.isValid);
return toValue(this.isValid);
}

protected ensureGetField<I extends AnyElementInstance>(name: string): I {
Expand Down Expand Up @@ -210,13 +212,13 @@ export class Form<V extends FormValues = FormValues> {
watch(instance.ref, async (value: unknown) => {
await this.hooks.execute(FormHook.ElementChange, this, instance, value);

if (!get(instance.isDisabled)) {
if (!toValue(instance.isDisabled)) {
// @ts-expect-error todo
this.values[elementConfig.name] = value as V[keyof V];
}
});

if (!get(instance.isDisabled)) {
if (!toValue(instance.isDisabled)) {
// @ts-expect-error todo
this.values[elementConfig.name] = unref(instance.ref) as V[keyof V];
}
Expand Down
Loading

0 comments on commit 2185f6f

Please sign in to comment.