Come accedere a un elemento DOM in React? Qual è l'equivalente di document.getElementById () in React


205

Come seleziono determinate barre in React.js?

Questo è il mio codice:

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 (...);
    }

Voglio usare questo componente React:

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>
        )
    }
});

Voglio eseguire la funzione handleClick10 ed eseguire l'operazione per la mia barra di avanzamento selezionata. Ma il risultato che ottengo è:

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

Come seleziono un determinato elemento in React.js?

Risposte:


215

Puoi farlo specificando il ref

EDIT: In reagire v16.8.0 con componente funzionale, è possibile definire un riferimento con useRef. Si noti che quando si specifica un riferimento a un componente funzionale, è necessario utilizzare React.forwardRef su di esso per inoltrare il riferimento all'elemento DOM di utilizzo useImperativeHandleper esporre alcune funzioni all'interno del componente funzionale

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} />
        </>
    )
}

MODIFICARE:

In React 16.3+ , usa React.createRef()per creare il tuo riferimento:

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

Per accedere all'elemento, utilizzare:

const node = this.myRef.current;

DOC per l'utilizzo di React.createRef ()


MODIFICARE

Tuttavia Facebook lo sconsiglia perché i riferimenti alle stringhe hanno alcuni problemi, sono considerati legacy e probabilmente verranno rimossi in una delle versioni future.

Dai documenti:

API legacy: riferimenti stringa

Se hai lavorato con React in precedenza, potresti avere familiarità con un'API precedente in cui l'attributo ref è una stringa, come "textInput", e al nodo DOM è possibile accedere come this.refs.textInput. Sconsigliamo perché i riferimenti alle stringhe presentano alcuni problemi, sono considerati legacy e probabilmente verranno rimossi in una delle versioni future. Se stai utilizzando this.refs.textInput per accedere a ref, ti consigliamo invece il modello di callback.

Un modo raccomandato per React 16.2 e precedenti è usare il modello di callback:

<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 per l'utilizzo del callback


Anche le versioni precedenti di ref definiti da reatt utilizzano stringhe come di seguito

<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"/>

Per ottenere l'elemento basta farlo

var object = this.refs.Progress1;

Ricorda di usare thisall'interno di un blocco funzione freccia come:

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

e così via...


5
Facebook sconsiglia questo approccio. Vedi qui facebook.github.io/react/docs/refs-and-the-dom.html
Dmitry

4
@dmitrymar Come posso vedere la pagina sopra è scritta per v15.4.2 in poi e immagino, questo non era prima quando ho scritto la risposta. Ad ogni modo, la risposta è stata modificata con l'approccio corretto
Shubham Khatri,

2
@MattSidor, grazie per la modifica, mi hai fatto risparmiare un po 'di tempo :-)
Shubham Khatri,

Ehm, domanda cosa succede se non riesco ad accedervi tramite "this", come se il componente di cui ho bisogno è un'istanza di un'altra classe? (ovvero un altro componente di reazione del bambino all'interno del componente principale)
akshay kishore

@akshaykishore Dovresti passare l'arbitro utilizzando un altro nome, dire innerRef e passarlo al componente desiderato
Shubham Khatri,

37

Per ottenere l'elemento in reactè necessario utilizzare refe all'interno della funzione è possibile utilizzare il ReactDOM.findDOMNodemetodo.

Ma quello che mi piace fare di più è chiamare l'arbitro proprio all'interno dell'evento

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

Questo è un buon link per aiutarti a capire.


2
Questo è il modo corretto per farlo. Questo aggiunge un riferimento all'elemento sull'oggetto / classe a cui puoi semplicemente usare this.myTextInputper accedere.
Sam Parmenter,

1
Come posso farlo con l'elemento creato dinamicamente?
Sagar Kodte,

Chiamare React.findDOMNodemi dàreact__WEBPACK_IMPORTED_MODULE_0___default.a.findDOMNode is not a function
James Poulose il

@JamesPoulose assicurati di non essere in esecuzione in modalità rigorosa, perché reagire non ti consentirà di utilizzare React.findDOMNodein modalità rigorosa.
Limpuls l'

13

È possibile sostituire

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

con

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


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

3
Come posso farlo con l'elemento creato dinamicamente?
Sagar Kodte,

1

Poiché React utilizza il codice JSX per creare un HTML, non possiamo fare riferimento a dom usando metodi di regolazione come documment.querySelector o getElementById.

Invece possiamo usare il sistema di riferimento di React per accedere e manipolare Dom come mostrato nell'esempio seguente:

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}
             />

        );

}

}


1
Questo non è vero. Puoi aggiungere un id all'elemento img, afferrarlo usando document.getElementById e, nella maggior parte dei casi, funzionerà bene. Potrebbe causare problemi / rendere più difficile il debug del codice, ma reagire / jsx non farlo in modo che CANT usi i metodi Dom nativi
adam tropp
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.