useFormControlValue()
function useFormControlValue<T>(control): T;
Defined in: hooks/useFormControlValue.ts:171
React-хук для подписки только на значение поля.
Оптимизированная версия useFormControl, которая подписывается
только на сигнал value. Компонент не будет ре-рендериться при изменении
errors, touched, valid и других свойств состояния.
Когда использовать
- Условный рендеринг на основе значения другого поля
- Вычисляемые значения зависящие от значения поля
- Read-only отображение значения без интерактивности
- Оптимизация производительности когда не нужны другие свойства состояния
Когда НЕ использовать
Если компоненту нужны errors, touched, disabled или другие свойства -
используйте useFormControl. Множественные подписки на один контрол
через разные хуки менее эффективны, чем одна подписка через useFormControl.
Type Parameters
T
T extends FormValue
Тип значения поля
Parameters
control
FieldNode<T>
FieldNode для подписки на значение
Returns
T
Текущее значение поля
Examples
import { useFormControlValue } from '@reformer/core';
interface FormFields {
hasShipping: FieldNode<boolean>;
shippingAddress: GroupNode<AddressFields>;
}
function ShippingSection({ form }: { form: FormFields }) {
// Подписка только на значение checkbox
const hasShipping = useFormControlValue(form.hasShipping);
if (!hasShipping) {
return null;
}
return (
<div className="shipping-section">
<h3>Shipping Address</h3>
<AddressForm control={form.shippingAddress} />
</div>
);
}
interface FormFields {
country: FieldNode<string>;
city: FieldNode<string>;
}
function CitySelect({ form }: { form: FormFields }) {
const country = useFormControlValue(form.country);
const { value, disabled } = useFormControl(form.city);
// Получаем города для выбранной страны
const cities = useMemo(() => getCitiesForCountry(country), [country]);
// Сбрасываем город при смене страны
useEffect(() => {
form.city.setValue('');
}, [country, form.city]);
return (
<select
value={value}
disabled={disabled || !country}
onChange={e => form.city.setValue(e.target.value)}
>
<option value="">Select city...</option>
{cities.map(city => (
<option key={city.id} value={city.id}>{city.name}</option>
))}
</select>
);
}
interface OrderItem {
quantity: FieldNode<number>;
price: FieldNode<number>;
}
function OrderTotal({ items }: { items: ArrayNode<OrderItem> }) {
// Для каждого элемента получаем только значения
const quantities = items.map(item => useFormControlValue(item.controls.quantity));
const prices = items.map(item => useFormControlValue(item.controls.price));
const total = quantities.reduce((sum, qty, i) => sum + qty * prices[i], 0);
return (
<div className="order-total">
<strong>Total: ${total.toFixed(2)}</strong>
</div>
);
}
interface MarkdownEditorProps {
control: FieldNode<string>;
}
function MarkdownPreview({ control }: MarkdownEditorProps) {
// Подписка только на значение для preview
const markdown = useFormControlValue(control);
const html = useMemo(() => marked(markdown), [markdown]);
return (
<div
className="markdown-preview"
dangerouslySetInnerHTML={{ __html: html }}
/>
);
}
// Основной редактор использует useFormControl для полного состояния
function MarkdownEditor({ control }: MarkdownEditorProps) {
const { value, shouldShowError, errors } = useFormControl(control);
return (
<div className="editor-container">
<textarea
value={value}
onChange={e => control.setValue(e.target.value)}
/>
{shouldShowError && <span className="error">{errors[0]?.message}</span>}
{/* Preview обновляется только при изменении value *}
<MarkdownPreview control={control} />
</div>
);
}
function CharacterCounter({ control, max }: { control: FieldNode<string>; max: number }) {
const value = useFormControlValue(control);
const remaining = max - value.length;
return (
<span className={remaining < 20 ? 'warning' : ''}>
{remaining} characters remaining
</span>
);
}
See
- useFormControl - для полного состояния поля
- FieldNode - тип контрола поля