Ref.current не определен при монтировании компонента и не может вызвать рендер, когда он мне нужен - PullRequest
3 голосов
/ 24 января 2020

Я хочу создать перетаскиваемый div, поэтому я создал ссылку для доступа к div, чтобы я мог использовать его в Rx js из оператора 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;

Ответы [ 2 ]

1 голос
/ 24 января 2020

вот окончательный код, который отлично работает для перетаскиваемого div в React

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;

1 голос
/ 24 января 2020

Вы можете использовать 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])
...