如何通过 refs 在 React 中聚焦输入

How to focus an input in React via refs

我正在使用 React JS,但遇到了问题。

我在页面上有一个组件,其中包含一些 inputs。当用户单击任何 input 时,应在下方创建一个新块,并且必须同时关注相同的 input

一切正常,直到我创建了一个展示逻辑:

const readyBlock = isTouched ? <ViewModule textInput={textInput}/> : null;

之后我得到× TypeError: 无法读取 属性 'focus' of null

下面是我的主要组件,页面上的所有内容都在这里发生。

const Sales = () => {
    const [isTouched, setIsTouched] = useState(false);
    const textInput = useRef(null);


    function handleInput() {
        setIsTouched(true);

        textInput.current.focus();
    }

    const readyBlock = isTouched ? <ViewModule textInput={textInput}/> : null;
    return (
        <main className="sales-page">
            <div className="main__title">
                <h2 className="main__heading">Bonuses</h2>
            </div>
            <div className="content-container">
                <UploadForm>
                    <FileUploadInput 
                        handleChange={handleInput}
                        placeholder="Header"/>
                    <FileUploadTextArea placeholder="Descr"/>
                </UploadForm>
            </div>
            <div className="ready-container ">
                {readyBlock}
            </div>
        </main>
    )
}

const ViewModule = ({textInput}) => {
    return (
        <UploadForm classNames="textarea-written">
            <FileUploadInput 
                ref={textInput}
                placeholder="Заголовок"/>
            <FileUploadTextArea placeholder="Descr"/>
            <div className="btn-container">
                <Btn classNames="cancel-btn">Cancel</Btn>
                <Btn>Save</Btn>
            </div>
        </UploadForm>
    )
}

下面是一个输入组件:

const FileUploadInput = React.forwardRef((props, ref) => {
    
    return (
        <div className="text-input-wrapper">
            <input
                ref={ref} 
                type="text" 
                id="file-text-input" 
                name="file__upload-title" 
                placeholder={props.placeholder}
                onClick={props.handleChange} />
        </div>
    )
});

我假设您希望在添加 ViewModule 组件时聚焦它。 问题是在将 ViewModule 添加到 DOM 树之前,Ref textInput 未分配给任何组件。您必须先在状态更改时将 ViewModule 添加到 DOM 树,然后在 useEffect 挂钩中您会发现正确分配了 textInput Ref。

function handleInput() {
   setIsTouched(true);
}

useEffect(() => {
   if (textInput.current === null) return
   if (isTouched) textInput.current.focus();
}, [isTouched])

您还应该使用 React.forwardRef 将 textInput Ref 传递给 ViewModule,就像您对 FileUploadInput 所做的那样。

const ViewModule = React.forwardRef((ref) => {...});

然后像这样使用它。

const readyBlock = isTouched ? <ViewModule ref={textInput}/> : null;