【问题标题】:React Hook (useState, setState) is both true and falseReact Hook (useState, setState) 是真假
【发布时间】:2021-06-13 18:16:33
【问题描述】:

所以我有一个 React 状态变量 const [pickingHotspot, setPickingHotspot] = useState(false);。然后我有这个按钮<button type="button" className="btn btn-outline-danger" onClick={() => setPickingHotspot(true)}>,它只是将状态设置为true onClick。我有另一个处理程序

tmp.on('mousedown', (event) => {
    if (pickingHotspot){
        console.log(tmp.mouseEventToCoords(event));
    } else {
        console.log(pickingHotspot);
    }
});

tmp 是一个 Pannellum 360 图像查看器(它是一个第三方库,但我认为它是什么并不重要),这是在我的 useState(...,[]) 中设置的,它在加载时运行一次。最后,我有一个 onClick div,它只打印 pickingHotspot 的值以进行调试。这是奇怪的部分:

当我加载页面并单击调试 div 时,该值为 false。酷,这行得通。然后我单击按钮(应该将其设置为 true!),然后再次单击调试 div。价值是真的!但是当我单击 Pannellum 查看器时,该值为 false?我不确定这个值怎么可能同时为真假,这取决于我点击的位置。这些变量是否有不同的版本/实例?我已经尝试将所有内容链接到 html 组件之外和 useEffect 之外的单个函数处理程序,以防发生一些奇怪的范围事情,但到目前为止没有任何效果。

我试图展示所有需要的代码,但这里是完整的(我去掉了大部分不相关的东西来简化它,它有很多代码需要查看。):

function TourCreator(props){

    
    const [scenes, setScenes] = useState({});
    const [media, setMedia] = useState({});
    const [viewer, setViewer] = useState(null);

    // Editor states
    const [pickingHotspot, setPickingHotspot] = useState(false);


    

    function handle(event){
        if (pickingHotspot){
            console.log(viewer.mouseEventToCoords(event));
        } else {
            console.log(pickingHotspot);
        }
    }


    // Called once on load
    useEffect(() => {

        if (Object.keys(media).length == 0){

            // Sends the request to the backend for "data"
            sendGetRequest(window.$PROJECT, true, {
                id: params["project_id"],
            }).then((data) => {

                data.images = reshapeArray(data.images, 3);
                console.log(data)

                setMedia(data);
                let tmp = window.pannellum.viewer('panorama', tour)
                setViewer(tmp);

                // Print Pitch/Yaw on click
                tmp.on('mousedown', (event) => handle(event));
                
            });
        }  
        
    }, [])

    
    return (
        <div className="p-3">

            
            {/* MAIN CONTENT */}
            <div className='tour-creator-root mx-auto p-3 row rounded'>

                {/* MAIN BOX */}
                <div className='main-box col-9 px-0 rounded'>

                    {/* Pannellum viewer */}
                    <div id='panorama' className="w-100 rounded-top">
                        <button type="button" className="save-button btn btn-outline-danger">
                            Save
                        </button>

                    </div>


                    {/* Toolbar */}
                    <div className="toolbar w-100 d-flex flex-column justify-content-center rounded-bottom p-3"
                    onClick={
                        () => {
                            console.log(pickingHotspot)
                        }
                    }>

                        <div className="d-flex flex-row justify-content-around">

                            <button type="button" className="btn btn-outline-danger" onClick={
                                () => setPickingHotspot(true)
                            }>
                                Add Hotspot
                            </button>

                        </div>

                    </div>


                </div>

                
            </div>

        </div>
    )

}


export default TourCreator;

【问题讨论】:

  • 这可能是因为您的依赖数组(useEffect) 缺少pickingHotspot 值。事件处理程序添加一次,然后再次引用当时的pickingHotspot 值。所以总是假的。尝试在你的依赖数组中传递 PickingHotspot 以获得 useEffect。
  • 尝试 Tushar 的答案并通过以下方式更改您的 onClick 函数:onClick={() => setPickingHotspot(!pickingHotspot)}
  • @TusharShahi 谢谢!你的回答确实有效。我仍然不完全理解为什么 React 将值解释为相同,但我会使用它。现在唯一发生的另一件事是,因为useEffect 在每次更改pickingHotspot 时都会被调用,所以每次更改时都会添加另一个事件处理程序。有没有办法覆盖这个或删除以前的事件处理程序?
  • 检查我的答案。

标签: javascript html reactjs


【解决方案1】:

尝试在你的依赖数组中传递pickHotspot以获得useEffect。

由于依赖项数组为空,因此您的事件处理程序在 componentDidMount 上的 useEffect 中附加到您的元素。这只会发生一次,并且将使用旧功能。旧函数将close 超过前一个状态的值。您可以通过在 dependency array 中传递 pickHotSpot 来再次附加您的事件处理程序。

将所有相关代码保留在挂钩中也是一种推荐的方法。您可以将侦听器函数放在钩子中,并且会从您的一个 lint 工具中看到缺少依赖项的警告。

另外,如果没有特定原因让您从 javascript 添加像这样的事件处理程序,然后像 @MB__ 建议的那样在 JSX 中添加内联使用。这将在每次渲染时执行,因此它应该是正确的。在任何时候都只会附加一个特定事件的事件处理程序。

【讨论】:

  • 太棒了,谢谢!刚刚开始工作。我以前从未听说过陈旧的东西,所以这非常有帮助。
  • 太棒了。如果这对您有帮助,请考虑投票/接受。
猜你喜欢
  • 1970-01-01
  • 2020-03-17
  • 2021-04-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多