【问题标题】:Ref.current is undefined when component mount and it can not cause a re render when I need it组件挂载时 Ref.current 未定义,当我需要它时它不会导致重新渲染
【发布时间】:2020-05-10 12:57:54
【问题描述】:

我想制作一个可拖动的 div,所以我创建了一个 ref 来访问该 div,这样我就可以在 Rxjs fromEvent 运算符中使用它

问题是 ref 对象在 fromEvent 中使用后会设置(第一次 ref 还没有设置)所以我把它放在 if 语句中,所以它只在设置时使用 ref。

现在dragRef.current 已设置,但组件不再执行

这是我正在使用的代码:

import React, { useRef, useEffect, useState } from "react";
import "./App.css";
import { fromEvent } from "rxjs";
import { map } from "rxjs/operators";

const App: React.FC = () => {
    const dragRef = useRef<HTMLDivElement>(null);

    const mouseMove = fromEvent(document, "mousedown");

    if (dragRef.current != undefined) {
        debugger;
        const mouseDown = fromEvent(dragRef.current, "mousedown");
        const mouseUp = fromEvent(dragRef.current, "mouseup");
        const mouseDrag = mouseDown.pipe(
            map((evt: MouseEvent | Event) => {
                // let offsetX = evt.clientX - dragRef.current.offsetLeft;
                // let offsetY = evt.clientY - dragRef.current.offsetTop;
                console.log(evt);
                return evt;
            })
        );
        mouseDrag.subscribe(v => console.log(v));
    }

    return (
        <div className="App">
            <header className="App-header">
                <div className="drag" ref={dragRef}></div>
            </header>
        </div>
    );
};

export default App;

【问题讨论】:

    标签: reactjs typescript react-ref


    【解决方案1】:

    您可以使用useEffect hook,它将您想要监视的变量数组作为依赖项。 因此,在您的情况下,当您的 ref 更改时,您将执行该函数。 类似的东西

    useEffect(() => {
    if (dragRef.current != undefined) {
            debugger;
            const mouseDown = fromEvent(dragRef.current, "mousedown");
            const mouseUp = fromEvent(dragRef.current, "mouseup");
            const mouseDrag = mouseDown.pipe(
                map((evt: MouseEvent | Event) => {
                    // let offsetX = evt.clientX - dragRef.current.offsetLeft;
                    // let offsetY = evt.clientY - dragRef.current.offsetTop;
                    console.log(evt);
                    return evt;
                })
            );
            mouseDrag.subscribe(v => console.log(v));
        }
    }, [dragRef])
    

    【讨论】:

    • 谢谢,它现在可以工作了,但我不知道我之前错在哪里,它给了我一个警告,说 dragRef 无法重新渲染组件,所以将它从 useEffect 依赖项中删除,因为它没有做任何东西
    【解决方案2】:

    这是最终代码,它非常适合 React 中的可拖动 div

    import React, { useRef, useEffect, useState } from "react";
    import "./App.css";
    import { fromEvent } from "rxjs";
    import { map, takeUntil, mergeMap } from "rxjs/operators";
    
    const App: React.FC = () => {
      const dragRef = useRef<HTMLDivElement>(null);
      const [position, setPosition] = useState({top: 100, left: 100})
    
        useEffect(() => {
            if (dragRef != null) {
                const mouseMove = fromEvent(document, "mousemove");
                //@ts-ignore
                const mouseDown = fromEvent(dragRef.current, "mousedown");
                //@ts-ignore
                const mouseUp = fromEvent(dragRef.current, "mouseup");
                const mouseDrag = mouseDown.pipe(
                    mergeMap((evt: any) => {
                        //@ts-ignore
                        let offsetX = evt.clientX - dragRef!.current.offsetLeft;
                        //@ts-ignore
                        let offsetY = evt.clientY - dragRef!.current.offsetTop;
                        return mouseMove.pipe(
                map((e: any) => ({
                  top: e.clientY - offsetY,
                                left: e.clientX - offsetX
                            })),
                takeUntil(mouseUp),
                        );
                    })
          );
    
                mouseDrag.subscribe((value: any) => {
            console.log(value)
                    setPosition(value)
                });
            }
        }, [dragRef]);
    
        return (
            <div className="App">
                <header className="App-header">
                    <div className="drag" ref={dragRef} style={{top: position.top +'px', left: position.left +'px'}}></div>
                </header>
            </div>
        );
    };
    
    export default App;
    
    

    【讨论】:

      猜你喜欢
      • 2022-01-06
      • 1970-01-01
      • 1970-01-01
      • 2021-07-15
      • 2021-11-23
      • 2021-09-18
      • 2021-05-23
      • 1970-01-01
      • 2021-01-17
      相关资源
      最近更新 更多