Wie greife ich in React auf ein DOM-Element zu? Was ist das Äquivalent von document.getElementById () in React?

202

Wie wähle ich bestimmte Balken in react.js aus?

Das ist mein Code:

var Progressbar = React.createClass({
    getInitialState: function () {
        return { completed: this.props.completed };
    },
    addPrecent: function (value) {
        this.props.completed += value;
        this.setState({ completed: this.props.completed });
    },

    render: function () {

        var completed = this.props.completed;
        if (completed < 0) { completed = 0 };


        return (...);
    }

Ich möchte diese React-Komponente verwenden:

var App = React.createClass({
    getInitialState: function () {

        return { baction: 'Progress1' };
    },
    handleChange: function (e) {
        var value = e.target.value;
        console.log(value);
        this.setState({ baction: value });
    },
    handleClick10: function (e) {
        console.log('You clicked: ', this.state.baction);
        document.getElementById(this.state.baction).addPrecent(10);
    },
    render: function () {
        return (
            <div class="center">Progress Bars Demo
            <Progressbar completed={25} id="Progress1" />
                <h2 class="center"></h2>
                <Progressbar completed={50} id="Progress2" />
                <h2 class="center"></h2>
                <Progressbar completed={75} id="Progress3" />
                <h2 class="center"></h2>
                <span>
                    <select name='selectbar' id='selectbar' value={this.state.baction} onChange={this.handleChange}>
                        <option value="Progress1">#Progress1</option>
                        <option value="Progress2">#Progress2</option>
                        <option value="Progress3">#Progress3</option>
                    </select>
                    <input type="button" onClick={this.handleClick10} value="+10" />
                    <button>+25</button>
                    <button>-10</button>
                    <button>-25</button>
                </span>
            </div>
        )
    }
});

Ich möchte die handleClick10-Funktion ausführen und die Operation für meinen ausgewählten Fortschrittsbalken ausführen. Aber das Ergebnis ist:

 You clicked:  Progress1
 TypeError: document.getElementById(...) is null

Wie wähle ich das bestimmte Element in react.js aus?

user504909
quelle

Antworten:

213

Sie können dies tun, indem Sie das angeben ref

BEARBEITEN : In Reaktion v16.8.0 mit Funktionskomponente können Sie mit useRef eine Referenz definieren. Beachten Sie, dass Sie, wenn Sie eine Referenz für eine Funktionskomponente angeben, React.forwardRef verwenden müssen, um die Referenz an das verwendete DOM-Element weiterzuleiten und useImperativeHandlebestimmte Funktionen innerhalb der Funktionskomponente verfügbar zu machen

Ex:

const Child1 = React.forwardRef((props, ref) => {
    return <div ref={ref}>Child1</div> 
});

const Child2 = React.forwardRef((props, ref) => {
    const handleClick= () =>{};
    useImperativeHandle(ref,() => ({
       handleClick
    }))
    return <div>Child2</div> 
});
const App = () => {
    const child1 = useRef(null);
    const child2 = useRef(null);

    return (
        <>
           <Child1 ref={child1} />
           <Child1 ref={child1} />
        </>
    )
}

BEARBEITEN:

Verwenden Sie in React 16.3+ , React.createRef()um Ihre Referenz zu erstellen:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

Verwenden Sie zum Zugriff auf das Element:

const node = this.myRef.current;

DOC für die Verwendung von React.createRef ()


BEARBEITEN

Facebook rät jedoch davon ab, da String-Refs einige Probleme haben, als Legacy gelten und wahrscheinlich in einer der zukünftigen Versionen entfernt werden.

Aus den Dokumenten:

Legacy-API: String Refs

Wenn Sie zuvor mit React gearbeitet haben, kennen Sie möglicherweise eine ältere API, bei der das ref-Attribut eine Zeichenfolge wie "textInput" ist und auf den DOM-Knoten als this.refs.textInput zugegriffen wird. Wir raten davon ab, da String-Refs einige Probleme haben, als Legacy gelten und wahrscheinlich in einer der zukünftigen Versionen entfernt werden. Wenn Sie derzeit this.refs.textInput verwenden, um auf refs zuzugreifen, empfehlen wir stattdessen das Rückrufmuster.

Eine empfohlene Methode für React 16.2 und frühere Versionen ist die Verwendung des Rückrufmusters:

<Progressbar completed={25} id="Progress1" ref={(input) => {this.Progress[0] = input }}/>

<h2 class="center"></h2>

<Progressbar completed={50} id="Progress2" ref={(input) => {this.Progress[1] = input }}/>

  <h2 class="center"></h2>

<Progressbar completed={75} id="Progress3" ref={(input) => {this.Progress[2] = input }}/>

DOC für die Verwendung von Rückruf


Auch ältere Versionen von reagieren definierten Refs mit einem String wie unten

<Progressbar completed={25} id="Progress1" ref="Progress1"/>

    <h2 class="center"></h2>

    <Progressbar completed={50} id="Progress2" ref="Progress2"/>

      <h2 class="center"></h2>

    <Progressbar completed={75} id="Progress3" ref="Progress3"/>

Um das Element zu erhalten, tun Sie es einfach

var object = this.refs.Progress1;

Denken Sie daran, thisin einem Pfeil Funktionsblock wie folgt zu verwenden :

print = () => {
  var object = this.refs.Progress1;  
}

und so weiter...

Shubham Khatri
quelle
5
Facebook rät von diesem Ansatz ab. Siehe hier facebook.github.io/react/docs/refs-and-the-dom.html
Dmitry
4
@dmitrymar Wie ich sehen kann, ist die obige Seite für Version 15.4.2 geschrieben und ich denke, dies war nicht früher da, als ich die Antwort schrieb. Wie auch immer, bearbeitet die Antwort mit dem richtigen Ansatz
Shubham Khatri
2
@ MattSidor, danke für die Bearbeitung, du hast mir etwas Zeit gespart :-)
Shubham Khatri
Frage: Was ist, wenn ich nicht über das "Dies" darauf zugreifen kann? Was ist, wenn die Komponente, die ich benötige, eine Instanz einer anderen Klasse ist? (dh ein anderes Kind reagiert Komponente innerhalb der Elternkomponente)
Akshay Kishore
@akshaykishore Sie müssten den Schiedsrichter unter einem anderen Namen weitergeben, sagen wir innerRef, und ihn an die gewünschte Komponente weitergeben
Shubham Khatri
37

Um das Element zu erhalten react, müssen Sie es verwenden, refund innerhalb der Funktion können Sie die ReactDOM.findDOMNodeMethode verwenden.

Aber was ich mehr tun möchte, ist, den Schiedsrichter direkt innerhalb des Events anzurufen

<input type="text" ref={ref => this.myTextInput = ref} />

Dies ist ein guter Link , der Ihnen hilft, dies herauszufinden.

EQuimper
quelle
2
Dies ist der richtige Weg, dies zu tun. Dadurch wird ein Verweis auf das Element im Objekt / in der Klasse hinzugefügt, auf den Sie einfach this.myTextInputzugreifen können.
Sam Parmenter
1
Wie kann ich das mit dynamisch erstellten Elementen machen?
Sagar Kodte
Berufung React.findDOMNodegibt mirreact__WEBPACK_IMPORTED_MODULE_0___default.a.findDOMNode is not a function
James Poulose
@JamesPoulose stellt sicher, dass Sie nicht im strengen Modus ausgeführt werden, da Sie mit "Reagieren" nicht React.findDOMNodeim strengen Modus arbeiten können.
Limpuls
12

Sie können ersetzen

document.getElementById(this.state.baction).addPrecent(10);

mit

this.refs[this.state.baction].addPrecent(10);


  <Progressbar completed={25} ref="Progress1" id="Progress1"/>
Piyush.kapoor
quelle
3
Wie kann ich das mit dynamisch erstellten Elementen machen?
Sagar Kodte
1

Da React JSX-Code zum Erstellen eines HTML-Codes verwendet, können wir dom nicht mit Regulierungsmethoden wie documment.querySelector oder getElementById referenzieren.

Stattdessen können wir das React ref-System verwenden, um auf Dom zuzugreifen und ihn zu bearbeiten, wie im folgenden Beispiel gezeigt:

constructor(props){

    super(props);
    this.imageRef = React.createRef(); // create react ref
}

componentDidMount(){

    **console.log(this.imageRef)** // acessing the attributes of img tag when dom loads
}


render = (props) => {

const {urls,description} = this.props.image;
    return (

            <img
             **ref = {this.imageRef} // assign the ref of img tag here**
             src = {urls.regular} 
             alt = {description}
             />

        );

}

}}

Nikhil Kamani
quelle
1
Das ist nicht wahr. Sie können dem img-Element eine ID hinzufügen, diese mit document.getElementById abrufen. In den meisten Fällen funktioniert dies einwandfrei. Es kann Probleme verursachen / das Debuggen Ihres Codes erschweren, aber reagieren / jsx macht es nicht so, dass Sie keine nativen Dom-Methoden verwenden können
Adam Tropp