React Ref undefined 当 useEffect 钩子触发时

React Ref undefined when useEffect hook fires

提问人:Richard Jones 提问时间:11/17/2023 最后编辑:jonrsharpeRichard Jones 更新时间:11/17/2023 访问量:62

问:

我已经编写了一个组件,我希望在组件加载时将用户名字段聚焦。在我不得不使用否则,我收到错误“无法读取 null 的属性(读取'焦点')”,因为在钩子触发时没有加载 ref。useEffectsetTimeoutuseEffect

有人知道为什么会这样吗?

import {useEffect, useRef} from 'react';
import {Modal, Button, TextInput, Label} from 'flowbite-react';
import {Head, useForm} from '@inertiajs/react';

export default function Register() {
    const {data, setData, post, processing, errors, reset} = useForm({
        username: '',
        email: '',
        password: '',
    });

    const usernameInputRef = useRef(null);

    useEffect(() => {
        setTimeout((() =>{
            usernameInputRef.current.focus()
        }), 100)



        return () => {
            reset('password');
        };
    }, []);



    const submit = (e) => {
        e.preventDefault();
        post(route('register'));
    };

    return (
        <>
            <Head title="Register Now"/>
            <Modal show="true">
                <form className="overflow-scroll" onSubmit={submit}>
                    <Modal.Header>Sign Up</Modal.Header>
                    <Modal.Body>

                        <div>
                            <Label htmlFor="username" value="Username"/>

                            <TextInput
                                id="username"
                                name="username"
                                value={data.username}
                                className="mt-1 block w-full"
                                autoComplete="username"
                                onChange={(e) => setData('username', e.target.value)}
                                required
                                color={errors.username ? "failure" : ""}
                                helperText={
                                    <>
                                        <span className="font-medium">{errors.username}</span>
                                    </>
                                }
                                ref={usernameInputRef}
                            />
                        </div>

                        <div className="mt-4">
                            <Label htmlFor="email" value="Email"/>

                            <TextInput
                                id="email"
                                type="text"
                                name="email"
                                value={data.email}
                                className="mt-1 block w-full"
                                autoComplete="username"
                                onChange={(e) => setData('email', e.target.value)}
                                required
                                color={errors.email ? "failure" : ""}
                                helperText={
                                    <>
                                        <span className="font-medium">{errors.email}</span>
                                    </>
                                }
                            />

                        </div>

                        <div className="mt-4">
                            <Label htmlFor="password" value="Password"/>

                            <TextInput
                                id="password"
                                type="password"
                                name="password"
                                value={data.password}
                                className="mt-1 block w-full"
                                autoComplete="new-password"
                                onChange={(e) => setData('password', e.target.value)}
                                required
                                color={errors.password ? "failure" : ""}
                                helperText={
                                    <>
                                        <span className="font-medium">{errors.password}</span>
                                    </>
                                }
                            />
                        </div>
                    </Modal.Body>
                    <Modal.Footer>
                        <div className="flex items-center justify-end  w-full">
                            <Button type="submit" className="w-full text-center" disabled={processing}>Register</Button>
                        </div>
                    </Modal.Footer>
                </form>
            </Modal>
        </>
    );
}
javascript reactjs react-native react-hooks

评论

4赞 Ori Drori 11/17/2023
有一个道具,这将节省您对 ref 和 .TextInputautoFocususeEffect
1赞 Harrison 11/17/2023
正如@OriDrori所说,当元素与道具一起加载到 DOM 中时,您可以简单地自动对焦元素。值得注意的是,您应该首先检查是否有值,直到元素挂载后才会这样做,这是 ref.current “获取值”的示例autoFocususernameInputRef.current

答:

0赞 dcselek 11/17/2023 #1

我认为你应该检查usernameInputRef.current 试试这个:

useEffect(() => {
      setTimeout(() => {
        if (usernameInputRef.current) {
          usernameInputRef.current.focus();
        }
      }, 100);
      return () => {
        reset('password');
      };
    }, []);

useEffect(() => {
      setTimeout(() => {
        if (usernameInputRef.current) {
          usernameInputRef.current.focus();
        }
      }, 100);
    
      return () => {
        reset('password');
      };
    }, [usernameInputRef]);