Bagaimana cara mengakses elemen DOM di Bereaksi? Apa yang dimaksud dengan equilvalent of document.getElementById () di React

203

Bagaimana cara memilih bilah tertentu di react.js?

Ini kode saya:

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

Saya ingin menggunakan komponen Bereaksi ini:

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

Saya ingin menjalankan fungsi handleClick10 dan melakukan operasi untuk progressbar yang saya pilih. Tapi hasil yang saya dapatkan adalah:

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

Bagaimana cara memilih Elemen tertentu di react.js?

pengguna504909
sumber

Jawaban:

214

Anda dapat melakukannya dengan menentukan ref

EDIT: Di react v16.8.0 dengan komponen fungsional, Anda dapat mendefinisikan ref dengan useRef. Perhatikan bahwa ketika Anda menentukan ref pada komponen fungsional, Anda perlu menggunakan React.forwardRef di atasnya untuk meneruskan ref ke elemen penggunaan DOM useImperativeHandleuntuk mengekspos fungsi tertentu dari dalam komponen fungsional

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

EDIT:

Di Bereaksi 16.3+ , gunakan React.createRef()untuk membuat referensi Anda:

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

Untuk mengakses elemen, gunakan:

const node = this.myRef.current;

DOC untuk menggunakan React.createRef ()


EDIT

Namun Facebook menyarankan untuk tidak melakukannya karena ref string memiliki beberapa masalah, dianggap warisan, dan kemungkinan akan dihapus di salah satu rilis mendatang.

Dari dokumen:

Legacy API: String Refs

Jika Anda bekerja dengan React sebelumnya, Anda mungkin akrab dengan API yang lebih lama di mana atribut ref adalah string, seperti "textInput", dan simpul DOM diakses sebagai this.refs.textInput. Kami menyarankan untuk tidak melakukannya karena ref string memiliki beberapa masalah, dianggap warisan, dan kemungkinan akan dihapus dalam salah satu rilis mendatang. Jika saat ini Anda menggunakan this.refs.textInput untuk mengakses referensi, sebaiknya gunakan pola panggilan balik.

Cara yang disarankan untuk Bereaksi 16.2 dan sebelumnya adalah dengan menggunakan pola panggilan balik:

<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 untuk menggunakan panggilan balik


Bahkan versi yang lebih lama dari ref yang didefinisikan didefinisikan menggunakan string seperti di bawah ini

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

Untuk mendapatkan elemen lakukan saja

var object = this.refs.Progress1;

Ingatlah untuk menggunakan thisdi dalam blok fungsi panah seperti:

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

dan seterusnya...

Shubham Khatri
sumber
5
Facebook menyarankan agar pendekatan ini tidak dilakukan. Lihat di sini facebook.github.io/react/docs/refs-and-the-dom.html
Dmitry
4
@ Dmitrymar Seperti yang saya lihat halaman di atas ditulis untuk v15.4.2 dan seterusnya dan saya kira, ini tidak ada sebelumnya ketika saya menulis jawabannya. Anyways mengedit jawaban dengan pendekatan yang benar
Shubham Khatri
2
@MattSidor, terima kasih untuk suntingannya, Anda menyelamatkan saya beberapa waktu :-)
Shubham Khatri
Um, pertanyaan bagaimana jika saya tidak dapat mengaksesnya melalui "ini", seperti bagaimana jika komponen yang saya butuhkan adalah instance dari kelas lain? (yaitu komponen reaksi anak lain dalam komponen induk)
akshay kishore
@akshaykishore Anda harus meneruskan referensi menggunakan nama lain say innerRef dan meneruskannya ke komponen yang diinginkan
Shubham Khatri
37

Untuk mendapatkan elemen di dalamnya, reactAnda perlu menggunakan refdan di dalam fungsi Anda dapat menggunakan ReactDOM.findDOMNodemetode.

Tapi yang ingin saya lakukan lebih banyak adalah memanggil ref tepat di dalam acara tersebut

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

Ini adalah beberapa tautan yang bagus untuk membantu Anda mencari tahu.

EQuimper
sumber
2
Ini cara yang benar untuk melakukan ini. Ini menambahkan referensi ke elemen pada objek / kelas yang dapat Anda gunakan this.myTextInputuntuk mengakses.
Sam Parmenter
1
Bagaimana saya bisa melakukan ini dengan elemen yang dibuat secara dinamis?
Sagar Kodte
Memanggil React.findDOMNodememberi sayareact__WEBPACK_IMPORTED_MODULE_0___default.a.findDOMNode is not a function
James Poulose
@JamesPoulose pastikan Anda tidak menjalankan dalam mode ketat, karena reaksi tidak akan memungkinkan Anda untuk menggunakan React.findDOMNodedalam mode ketat.
Limpuls
12

Anda bisa mengganti

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

dengan

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


  <Progressbar completed={25} ref="Progress1" id="Progress1"/>
Piyush.kapoor
sumber
3
Bagaimana saya bisa melakukan ini dengan elemen yang dibuat secara dinamis?
Sagar Kodte
1

Karena Bereaksi menggunakan kode JSX untuk membuat HTML, kami tidak dapat merujuk dom menggunakan metode regulasi seperti documment.querySelector atau getElementById.

Sebagai gantinya kita dapat menggunakan React sistem ref untuk mengakses dan memanipulasi Dom seperti yang ditunjukkan pada contoh di bawah ini:

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
sumber
1
Ini tidak benar. Anda dapat menambahkan id ke elemen img, ambil dengan menggunakan document.getElementById, dan dalam kebanyakan kasus, itu akan berfungsi dengan baik. Ini dapat menyebabkan masalah / membuat kode Anda lebih sulit untuk di-debug, tetapi bereaksi / jsx jangan membuatnya sehingga Anda TIDAK BISA menggunakan metode Dom asli
adam tropp