Ich versuche, eine Bereichseingabe zu erstellen, die einen Tooltip direkt über dem Schieberegler-Daumen anzeigt.
Ich habe einige Vanilla JS-Beispiele online durchgesehen und es scheint, dass ich die Breite des Elements haben muss, um dies zu erreichen.
Also habe ich mich nur gefragt, wie ich die Breite der Elemente bekomme?
Ziemlich genau das Äquivalent der JQuery-Methode $(element).width()
Antworten:
class MyComponent extends Component { constructor(props){ super(props) this.myInput = React.createRef() } componentDidMount () { console.log(this.myInput.current.offsetWidth) } render () { return ( // new way - as of [email protected] <div ref={this.myInput}>some elem</div> // legacy way // <div ref={(ref) => this.myInput = ref}>some elem</div> ) } }
quelle
React.createRef()
Mit Haken :
const MyComponent = () => { const ref = useRef(null); useEffect(() => { console.log('width', ref.current ? ref.current.offsetWidth : 0); }, [ref.current]); return <div ref={ref}>Hello</div>; };
quelle
useRef
unduseEffect
Sie können einfach einen Rückruf ref im Beispiel oben verwenden.const ref = useRef<HTMLHeadingElement>(null);
Eigentlich wäre es besser, diese Größenänderungslogik in einem benutzerdefinierten Hook zu isolieren . Sie können einen benutzerdefinierten Hook wie folgt erstellen:
const useResize = (myRef) => { const [width, setWidth] = useState(0) const [height, setHeight] = useState(0) useEffect(() => { const handleResize = () => { setWidth(myRef.current.offsetWidth) setHeight(myRef.current.offsetHeight) } window.addEventListener('resize', handleResize) return () => { window.removeEventListener('resize', handleResize) } }, [myRef]) return { width, height } }
und dann können Sie es verwenden wie:
const MyComponent = () => { const componentRef = useRef() const { width, height } = useResize(componentRef) return ( <div ref={myRef}> <p>width: {width}px</p> <p>height: {height}px</p> <div/> ) }
quelle
handleResize()
auf den EventListeners oder useResize wird zurückkehren{ 0, 0}
useResize
muss `if (myRef.current) {<setWidth SetHeight etc,>)Dies ist im Grunde die Antwort von Marco Antônio für einen benutzerdefinierten React-Hook, der jedoch geändert wurde, um die Abmessungen zunächst und nicht erst nach einer Größenänderung festzulegen.
export const useContainerDimensions = myRef => { const getDimensions = () => ({ width: myRef.current.offsetWidth, height: myRef.current.offsetHeight }) const [dimensions, setDimensions] = useState({ width: 0, height: 0 }) useEffect(() => { const handleResize = () => { setDimensions(getDimensions()) } if (myRef.current) { setDimensions(getDimensions()) } window.addEventListener("resize", handleResize) return () => { window.removeEventListener("resize", handleResize) } }, [myRef]) return dimensions; };
Auf die gleiche Weise verwendet:
const MyComponent = () => { const componentRef = useRef() const { width, height } = useContainerDimensions(componentRef) return ( <div ref={componentRef}> <p>width: {width}px</p> <p>height: {height}px</p> <div/> ) }
quelle
Eine einfache und aktuelle Lösung ist die Verwendung des React React useRef-Hooks , der einen Verweis auf die Komponente / das Element speichert, kombiniert mit einem useEffect- Hook, der beim Rendern von Komponenten ausgelöst wird.
import React, {useState, useEffect, useRef} from 'react'; export default App = () => { const [width, setWidth] = useState(0); const elementRef = useRef(null); useEffect(() => { setWidth(elementRef.current.getBoundingClientRect().width); }, []); //empty dependency array so it only runs once at render return ( <div ref={elementRef}> {width} </div> ) }
quelle
if (!ref.current) return;
bevor Sie die Referenz verwenden, und das Hinzufügen der Referenz zum Abhängigkeitsarray, damit es wie[ref]
eine leereHier ist eine TypeScript-Version der Antwort von @ meseern , die unnötige Zuweisungen beim erneuten Rendern vermeidet:
import React, { useState, useEffect } from 'react'; export function useContainerDimensions(myRef: React.RefObject<any>) { const [dimensions, setDimensions] = useState({ width: 0, height: 0 }); useEffect(() => { const getDimensions = () => ({ width: (myRef && myRef.current.offsetWidth) || 0, height: (myRef && myRef.current.offsetHeight) || 0, }); const handleResize = () => { setDimensions(getDimensions()); }; if (myRef.current) { setDimensions(getDimensions()); } window.addEventListener('resize', handleResize); return () => { window.removeEventListener('resize', handleResize); }; }, [myRef]); return dimensions; }
quelle
Es empfiehlt sich, auf Ereignisse zur Größenänderung zu warten, um eine Größenänderung beim Rendern oder sogar eine Größenänderung des Benutzerfensters zu verhindern, die Ihre Anwendung beschädigen kann.
const MyComponent = ()=> { const myRef = useRef(null) const [myComponenetWidth, setMyComponentWidth] = useState('') const handleResize = ()=>{ setMyComponentWidth(myRef.current.offsetWidth) } useEffect(() =>{ if(myRef.current) myRef.current.addEventListener('resize', handleResize) return ()=> { myRef.current.removeEventListener('resize', handleResize) } }, [myRef]) return ( <div ref={MyRef}>Hello</div> ) }
quelle
Dies könnte möglicherweise auf einfachere Weise durch Verwendung von Rückrufreferenzen gehandhabt werden .
Mit React können Sie eine Funktion an eine Referenz übergeben, die das zugrunde liegende DOM-Element oder den zugrunde liegenden Komponentenknoten zurückgibt. Siehe: https://reactjs.org/docs/refs-and-the-dom.html#callback-refs
const MyComponent = () => { const myRef = node => console.log(node ? node.innerText : 'NULL!'); return <div ref={myRef}>Hello World</div>; }
Diese Funktion wird ausgelöst, wenn der zugrunde liegende Knoten geändert wird. Zwischen den Updates wird es null sein, daher müssen wir dies überprüfen. Beispiel:
const MyComponent = () => { const [time, setTime] = React.useState(123); const myRef = node => console.log(node ? node.innerText : 'NULL!'); setTimeout(() => setTime(time+1), 1000); return <div ref={myRef}>Hello World {time}</div>; } /*** Console output: Hello World 123 NULL! Hello World 124 NULL! ...etc ***/
Obwohl dies nicht die Größenänderung als solche behandelt (wir würden immer noch einen Listener für die Größenänderung benötigen, um die Größe des Fensters zu ändern), bin ich mir nicht sicher, ob das OP dies verlangt hat. In dieser Version wird die Größe des Knotens aufgrund eines Updates geändert.
Hier ist ein benutzerdefinierter Haken, der auf dieser Idee basiert:
export const useClientRect = () => { const [rect, setRect] = useState({width:0, height:0}); const ref = useCallback(node => { if (node !== null) { const { width, height } = node.getBoundingClientRect(); setRect({ width, height }); } }, []); return [rect, ref]; };
Das Obige basiert auf https://reactjs.org/docs/hooks-faq.html#how-can-i-measure-a-dom-node
Notieren Sie den Haken zurückkehrt einen ref Rückruf, anstatt dass sie bestanden einen ref. Und wir verwenden useCallback , um zu vermeiden, dass jedes Mal eine neue Ref-Funktion neu erstellt wird. nicht lebenswichtig, aber als gute Praxis angesehen.
Die Verwendung ist wie folgt (basierend auf dem Beispiel von Marco Antônio):
const MyComponent = ({children}) => { const [rect, myRef] = useClientRect(); const { width, height } = rect; return ( <div ref={myRef}> <p>width: {width}px</p> <p>height: {height}px</p> {children} <div/> ) }
quelle