简体   繁体   English

即使在 useEffect 中也没有设置 React useRef

[英]React useRef is not setting even in useEffect

I am attempting to show an image in a random position according to dynamic dimensions using a ref.我正在尝试根据使用参考的动态尺寸在随机 position 中显示图像。 However, when getting the useRef's current value, I recieve undefined likely because the useRef's target div hasn't loaded yet.但是,当获取 useRef 的当前值时,我可能会收到 undefined ,因为 useRef 的目标 div 尚未加载。

To overcome this, I am using a useEffect to wait for the target div to load.为了克服这个问题,我使用 useEffect 来等待目标 div 加载。

However, when I run the program the image does not move because the useRef's current value remains at 0. The但是,当我运行程序时,图像不会移动,因为 useRef 的当前值仍为 0。

import './MouseAim.css'
import '../Game.css'

import React, {useEffect, useRef, useState} from 'react'

import TargetImg from '../../../assets/Target.png'
import _ from "lodash";

function MouseAim() {
    const [start, setStart] = useState(true)
    const [target, setTarget] = useState(true)
    const elementDimensions = useRef()


    //wait for elementDimensions to be set
    useEffect(() => {
        console.log('elementDimensions', elementDimensions.current?.clientHeight)
    } , [elementDimensions])

    return (
        <div>
            <div className="main-container">
                {
                        start ?

                            <div ref={elementDimensions} className="aim-container">
                                {
                                    target ?
                                            <input 
                                                className="target" 
                                                type="image" 
                                                style={{position: "relative", left:elementDimensions.current?.clientHeight+"px" , top:_.random(0, elementDimensions.current?.clientHeight)+"px"}}
                                                onClick={() => console.log("hello")} 
                                                src={TargetImg} 
                                                alt="target"
                                            />
                                    :null
                                }
                            </div>

                        :
                            <div className="start-container">
                                <input className="start-button" type="button" value="Start Game" onClick={() => setStart(true)}/>
                            </div>
                }
            </div>
        </div>
    )
}

export default MouseAim

Just set your target initial state to 'false', then set it to true when 'ref' is ready只需将目标初始 state 设置为“false”,然后在“ref”准备好时将其设置为 true

Try this one:试试这个:

const [start, setStart] = useState(true)
const [target, setTarget] = useState(false)
const elementDimensions = useRef()


//wait for elementDimensions to be set
useEffect(() => {
    console.log('elementDimensions', elementDimensions.current?.clientHeight)
    setTarget(true)
} , [elementDimensions])

Just like you mentioned, the useRef is set very initially when the div has not been mounted.就像您提到的那样,当 div 尚未安装时,useRef 最初是设置的。

The div mounts when start becomes true.start变为 true 时,div 会挂载。 So that's where the trigger needs to happen.所以这就是需要触发的地方。

Try to pass start as the dependency variables to the useEffect .尝试将start作为依赖变量传递给useEffect

useEffect(() => {
        console.log('elementDimensions', elementDimensions.current?.clientHeight)
    } , [start, elementDimensions])

PS. PS。 If it doesn't work, pass target as the dependency variable as well.如果它不起作用,请将target也作为依赖变量传递。

useEffect(() => {
        console.log('elementDimensions', elementDimensions.current?.clientHeight)
    } , [start, target, elementDimensions])

I think separating your code into subcomponents will make this much simpler, as MouseAim has too much responsibility.我认为将您的代码分成子组件会使这变得更简单,因为MouseAim有太多的责任。 In general, giving your components one clearly-defined purpose is a good way to simplify your codebase.一般来说,给组件一个明确定义的目的是简化代码库的好方法。

const AimContainer = () => {
    const containerRef = useRef()
    const [containerSize, setContainerSize] = useState();

    useEffect(() => {
        // set container size state here
    }, [])

    return <div ref={containerRef}>...</div>
}

const MouseAim = () => {
    const [hasStarted, setHasStarted] = useState(false);

    return <div>
        { hasStarted ? 
            <AimContainer />
            :
            <button onClick={() => setHasStarted(true)}>Start</button>
        }
    </div>

}

AimContainer will render before running useEffect , so you may also want to avoid rendering the target until containerSize is set. AimContainer将在运行useEffect之前渲染,因此您可能还希望在设置containerSize之前避免渲染目标。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM