组件挂载时 Ref.current 未定义,当我需要它时它不会导致重新渲染

Posted

技术标签:

【中文标题】组件挂载时 Ref.current 未定义,当我需要它时它不会导致重新渲染【英文标题】:Ref.current is undefined when component mount and it can not cause a re render when I need it 【发布时间】: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;

【问题讨论】:

【参考方案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 依赖项中删除,因为它没有做任何东西 @TaghiKhavari 也许这会更好? reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node【参考方案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;

【讨论】:

以上是关于组件挂载时 Ref.current 未定义,当我需要它时它不会导致重新渲染的主要内容,如果未能解决你的问题,请参考以下文章

ReactJs:为啥 ref.current 在渲染组件时返回 null?

[Vue 警告]:无法挂载组件:未定义模板或渲染函数?

使用Effect清理功能,防止未挂载的组件异步更新

[Vue 警告]:无法挂载组件:未定义模板或渲染函数。错误

酶不会“渲染、挂载或浅化”组件,因为未定义依赖项

Laravel 6 + Vue.js 无法挂载组件:未定义模板或渲染函数