我有一個表單輸入組件,我正在檢查輸入是否處于活動狀態以將活動類設定為輸入的標簽:
import React, { forwardRef, ReactElement, ReactNode, HTMLProps, useImperativeHandle } from 'react'
import styles from './index.module.css'
import classNames from 'classnames'
import { IconFa } from '../icon-fa'
import { useStableId } from '../use-stable-id'
export interface Props extends HTMLProps<HTMLInputElement> {
// An icon component to show on the left.
icon?: ReactNode
// A help text tooltip to show on the right.
help?: string
// A clear text tooltip to show on the right.
clear?: string
// Pass an onHelp click handler to show a help button.
onHelp?: () => void
// Pass an onClear click handler to show a clear button.
onClear?: () => void
errorMessage?: ReactNode
label?: string
hideLabel?: boolean
}
export const FormInput = forwardRef<HTMLInputElement, Props>(function FormInput(props, ref): ReactElement {
const { id, icon, help, hideLabel, errorMessage, onHelp, onClear, ...rest } = props
const internalRef = React.useRef<HTMLInputElement>(null)
useImperativeHandle<HTMLInputElement | null, HTMLInputElement | null>(ref, () => internalRef.current)
const stableId = useStableId()
const inputId = id ? id : stableId
const active = document.activeElement === internalRef.current
const inputClassName = classNames(
styles.input,
icon && styles.hasLeftIcon,
(help || onHelp || onClear) && styles.hasRightIcon
)
const labelClassName = classNames(
styles.label,
Boolean(props.value) && styles.hasValue,
props['aria-invalid'] && styles.hasError,
active && styles.active,
props.className
)
return (
<div className={labelClassName}>
{!hideLabel && (
<label className={styles.labelText} htmlFor={inputId}>
{props.label}
{props.required && '*'}
</label>
)}
<div className="relative">
{icon && <div className={styles.leftIcon}>{icon}</div>}
<input
{...rest}
id={inputId}
ref={internalRef}
aria-invalid={props['aria-invalid']}
aria-label={props.hideLabel ? props.label : undefined}
className={inputClassName}
/>
{onClear && <ClearIcon {...props} />}
{!onClear && (help || onHelp) && <HelpIcon {...props} />}
</div>
{props['aria-invalid'] && <span className={styles.error}>{errorMessage}</span>}
</div>
)
})
function HelpIcon(props: Props) {
if (props.onHelp) {
return (
<button type="button" className={styles.rightIcon} aria-label={props.help} onClick={props.onHelp}>
<IconFa icon={['far', 'info-circle']} title={props.help} />
</button>
)
}
return (
<div className={styles.rightIcon} title={props.help}>
<IconFa icon={['far', 'info-circle']} />
</div>
)
}
function ClearIcon(props: Props) {
return (
<button type="button" className={styles.rightIcon} aria-label={props.clear} onClick={props.onClear}>
<IconFa icon={['far', 'times']} title={props.clear} />
</button>
)
}
但是,當我這樣做時,只有在我開始輸入時才將活動類添加到標簽中,而不是在輸入集中時。現在,由于我:focus在輸入上使用選擇器,因此輸入會在焦點上獲得活動類,而標簽僅在輸入后才會獲得。我該如何解決這個問題,以便他們都集中注意力?
uj5u.com熱心網友回復:
該active標志僅在組件重新渲染時重新評估,這就是為什么您僅在狀態更改時才看到更改的原因(例如,通過鍵入,這很可能會觸發父組件中的狀態更改,如果它使用onChange例如)。
在您的情況下,您似乎可以直接使用onFocusandonBlur偵聽器,并將active標志作為狀態:
export const FormInput = forwardRef<HTMLInputElement, Props>(function FormInput(props, ref) {
const [active, setActive] = useState(false)
const labelClassName = classNames(
active && styles.active
)
return (
<div className={labelClassName}>
<input
onFocus={() => setActive(true)}
onBlur={() => setActive(false)}
/>
</div>
)
})
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/508371.html
上一篇:如何根據TS修復功能?
