diff --git a/CHANGELOG.md b/CHANGELOG.md
index 939f8efe5..3639e5830 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## Next
+
+- **Fixed:** Regression of accepting non-string labels in `useField` and `connectField`. [\#816](https://github.com/vazco/uniforms/issues/816)
+
## [v3.0.0-rc.5](https://github.com/vazco/uniforms/tree/v3.0.0-rc.5) (2020-09-30)
- **Added:** New `disableItem` prop in `SelectField`. [\#736](https://github.com/vazco/uniforms/issues/736)
diff --git a/packages/uniforms/__tests__/connectField.tsx b/packages/uniforms/__tests__/connectField.tsx
index aafabd746..beea5dd46 100644
--- a/packages/uniforms/__tests__/connectField.tsx
+++ b/packages/uniforms/__tests__/connectField.tsx
@@ -1,4 +1,4 @@
-import React from 'react';
+import React, { ReactNode } from 'react';
import { SimpleSchema } from 'simpl-schema';
import { Context, connectField, randomIds } from 'uniforms';
import { SimpleSchemaBridge } from 'uniforms-bridge-simple-schema';
@@ -125,4 +125,61 @@ describe('connectField', () => {
expect(onChange).toBeCalledWith('field', 'initialValueExample');
});
});
+
+ // TODO: Write tests for `placeholder`.
+ describe('when rendered with label', () => {
+ const labelA = Error;
+ const labelB = OK;
+
+ it.each([
+ ['Props', '', false, 'Props'],
+ ['Props', '', true, 'Props'],
+ ['Props', 'Schema', false, 'Props'],
+ ['Props', 'Schema', true, 'Props'],
+ ['Props', labelB, false, 'Props'],
+ ['Props', labelB, true, 'Props'],
+ [false, '', false, ''],
+ [false, '', true, ''],
+ [false, 'Schema', false, ''],
+ [false, 'Schema', true, ''],
+ [false, labelB, false, ''],
+ [false, labelB, true, ''],
+ [labelA, '', false, labelA],
+ [labelA, '', true, labelA],
+ [labelA, 'Schema', false, labelA],
+ [labelA, 'Schema', true, labelA],
+ [labelA, labelB, false, labelA],
+ [labelA, labelB, true, labelA],
+ [true, '', false, ''],
+ [true, '', true, ''],
+ [true, 'Schema', false, 'Schema'],
+ [true, 'Schema', true, 'Schema'],
+ [true, labelB, false, labelB],
+ [true, labelB, true, labelB],
+ [undefined, '', false, ''],
+ [undefined, '', true, ''],
+ [undefined, 'Schema', false, ''],
+ [undefined, 'Schema', true, 'Schema'],
+ [undefined, labelB, false, ''],
+ [undefined, labelB, true, labelB],
+ ] as [ReactNode, ReactNode, boolean, ReactNode][])(
+ 'resolves it correctly (%#)',
+ (prop, schema, state, result) => {
+ const context: typeof reactContext = {
+ context: {
+ ...reactContext.context,
+ state: { ...reactContext.context.state, label: state },
+ },
+ };
+
+ jest
+ .spyOn(context.context.schema, 'getProps')
+ .mockReturnValueOnce({ label: schema });
+
+ const Field = connectField(Test);
+ const wrapper = mount(, context);
+ expect(wrapper.find(Test).prop('label')).toBe(result);
+ },
+ );
+ });
});
diff --git a/packages/uniforms/src/useField.tsx b/packages/uniforms/src/useField.tsx
index 8a4ce49a5..96d5710f5 100644
--- a/packages/uniforms/src/useField.tsx
+++ b/packages/uniforms/src/useField.tsx
@@ -1,30 +1,31 @@
import get from 'lodash/get';
import mapValues from 'lodash/mapValues';
-import { useCallback, useEffect, useMemo } from 'react';
+import { ReactNode, useCallback, useEffect, useMemo } from 'react';
import { joinName } from './joinName';
import { GuaranteedProps } from './types';
import { useForm } from './useForm';
function propagate(
- prop: unknown,
- schema: unknown,
+ prop: ReactNode,
+ schema: ReactNode,
state: boolean,
- fallback: string,
-): [string, string] {
- const schemaDisabled = schema === false || schema === '';
- const schemaValue =
- typeof schema === 'string' ? schema : schemaDisabled ? '' : fallback;
- const resultValue =
- typeof prop === 'string'
- ? prop
- : prop === null ||
- prop === false ||
- (prop === undefined && !state) ||
- schemaDisabled
+ fallback: ReactNode,
+): [ReactNode, ReactNode] {
+ const forcedFallbackInProp = prop === true || prop === undefined;
+ const forcedFallbackInSchema = schema === true || schema === undefined;
+
+ const schemaValue = forcedFallbackInSchema ? fallback : schema;
+ const value =
+ prop === '' ||
+ prop === false ||
+ (forcedFallbackInProp && (forcedFallbackInSchema || !state))
? ''
- : schemaValue;
- return [resultValue, schemaValue];
+ : forcedFallbackInProp
+ ? schemaValue
+ : prop;
+
+ return [value, schemaValue];
}
export function useField<
@@ -112,7 +113,8 @@ export function useField<
...props,
label,
name,
- placeholder,
+ // TODO: Should we assert `typeof placeholder === 'string'`?
+ placeholder: placeholder as string,
};
return [fieldProps, context] as [typeof fieldProps, typeof context];