我用React Hook Form
创建了一个自定义TextInput
,我正试图将焦点设置到下一个TextInput
。
我解释得更好:为了集中下一个元素,我可以很容易地创建这样的useRef
:
const passwordRef = useRef<HTMLInputElement>(null);
<FormProvider {...methods}>
<TextInput
name="email"
label="Email"
keyboardType="email-address"
autoCompleteType="email"
rules={{
required: true,
pattern: emailPattern,
}}
returnKeyType="next"
autoCapitalize="none"
autoCorrect={false}
errorLabel={{
type: "pattern",
label: "Your email isn't correct",
}}
onSubmitEditing={() => passwordRef.current?.focus()}
/>
<TextInput
name="password"
label="Password"
autoCompleteType="password"
returnKeyType="go"
rules={{ required: true }}
secureTextEntry={true}
inputRef={passwordRef}
blurOnSubmit={false}
onSubmitEditing={methods.handleSubmit(onSubmit)}
/>
</FormProvider>;
通过这种方式,我可以很容易地设置焦点,但我试图使其通用:TextInput
知道谁是下一个要关注的元素。
希望我的问题很清楚,任何建议都可以接受。
您的TextComponentWrapper
可以像(更新(
const TextInputWrapper = (props) => {
const [isFocused, setFocus] = useState(false);
const { currentIndex, inputsLength, forwardRef, onSubmit, nextFocusRef } =
props;
// create dynamic refs for inputs
const inputsRef = React.useRef([...Array(inputsLength)].map(() => React.createRef()));
const onSubmitEditing = () => {
inputsRef?.current[currentIndex + 1]?.current?.focus();
};
const onBlur = () => {
setFocus(false);
};
const onFocus = () => {
setFocus(true);
};
return (
<Input
onBlur={onBlur}
ref={inputsRef.current[currentIndex]}
onFocus={onFocus}
returnKeyType={onSubmit ? "done" : "next"}
onSubmitEditing={onSubmit || onSubmitEditing}
blurOnSubmit={false}
/>
);
};
export default TextInputWrapper;
创建类似的CustomHooks
import {useRef} from 'react';
export const useInputProps = (formObj, name) => {
const {control, errors} = formObj;
const inputRef = useRef(null);
return {forwardRef: inputRef, control: control, name, error: errors[name]};
};
类似的用法
import { useInputProps } from "./CustomHooks";
const emailProps = useInputProps(formObj, "email");
const passwordProps = useInputProps(formObj, "password");
<View>
<TextInput inputsLength={2} currentIndex={0} {...emailProps} />
<TextInput
inputsLength={2}
currentIndex={1}
onSubmit={methods.handleSubmit(onSubmit)}
{...passwordProps}
/>
</View>
您需要创建一个Wrapper
组件来封装TextInput
s,然后使用Children.map
动态遍历它们中的每一个,并在分配引用时添加onSubmitEditing
函数。
function Wrapper({ children, onLastOnSubmitEditing }) {
const arrayChildren = Children.toArray(children);
const childrenRef = useRef([]);
return <>{Children.map(arrayChildren, (child, index) => {
const onSubmitEditing = () => {
if (index < arrayChildren.length - 1) {
childrenRef.current[index+1].focus();
} else {
onLastOnSubmitEditing();
}
}
return cloneElement(child, { ref: (ref) => (childrenRef.current[index] = ref), onSubmitEditing });
})}</>
}
用法:
<FormProvider {...methods}>
<Wrapper onLastOnSubmitEnding={methods.handleSubmit(onSubmit)}>
<TextInput
name="email"
label="Email"
keyboardType="email-address"
autoCompleteType="email"
rules={{
required: true,
pattern: emailPattern,
}}
returnKeyType="next"
autoCapitalize="none"
autoCorrect={false}
errorLabel={{
type: "pattern",
label: "Your email isn't correct",
}}
/>
<TextInput
name="password"
label="Password"
autoCompleteType="password"
returnKeyType="go"
rules={{ required: true }}
secureTextEntry={true}
inputRef={passwordRef}
blurOnSubmit={false}
/>
</Wrapper>
</FormProvider>;
Codesandbox:https://codesandbox.io/s/suspicious-euclid-rqtrrb