จะเข้าถึงองค์ประกอบ DOM ใน React ได้อย่างไร อะไรคือความเท่าเทียมกันของ document.getElementById () ใน React


205

ฉันจะเลือกแท่งบางอย่างใน react.js ได้อย่างไร

นี่คือรหัสของฉัน:

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

ฉันต้องการใช้ส่วนประกอบ 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>
        )
    }
});

ฉันต้องการเรียกใช้งานฟังก์ชัน handleClick10 และดำเนินการสำหรับแถบความคืบหน้าที่เลือกไว้ แต่ผลลัพธ์ที่ฉันได้รับคือ:

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

ฉันจะเลือกองค์ประกอบบางอย่างใน react.js ได้อย่างไร

คำตอบ:


215

คุณสามารถทำได้โดยระบุ ref

แก้ไข:ในการตอบสนอง v16.8.0 ด้วยองค์ประกอบการทำงานคุณสามารถกำหนดการอ้างอิงด้วย useRef โปรดทราบว่าเมื่อคุณระบุการอ้างอิงในองค์ประกอบการทำงานคุณจะต้องใช้ React.forwardRef เพื่อส่งต่อการอ้างอิงไปยังองค์ประกอบ DOM ของการใช้งานuseImperativeHandleเพื่อแสดงฟังก์ชั่นบางอย่างจากภายในองค์ประกอบการทำงาน

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

แก้ไข:

ในการตอบสนอง 16.3+ให้ใช้React.createRef()เพื่อสร้างการอ้างอิงของคุณ:

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

เพื่อเข้าถึงองค์ประกอบให้ใช้:

const node = this.myRef.current;

DOC สำหรับการใช้ React.createRef ()


แก้ไข

อย่างไรก็ตาม facebook แนะนำว่าเพราะข้อความอ้างอิงมีปัญหาบางอย่างถือเป็นมรดกและมีแนวโน้มที่จะถูกลบออกในหนึ่งในอนาคต

จากเอกสาร:

Legacy API: การอ้างอิงสตริง

หากคุณเคยทำงานกับ React มาก่อนคุณอาจคุ้นเคยกับ API รุ่นเก่าที่มีการอ้างอิงแอตทริบิวต์เป็นสตริงเช่น "textInput" และเข้าถึงโหนด DOM เป็น this.refs.textInput เราแนะนำต่อเนื่องจากการอ้างอิงสตริงมีปัญหาบางอย่างถือเป็นมรดกและมีแนวโน้มที่จะถูกลบออกในหนึ่งในรุ่นที่ออกในอนาคต หากคุณกำลังใช้งานอยู่ในปัจจุบันนี้ฟอร์แมทข้อความอินพุตเพื่อเข้าถึงการอ้างอิงเราขอแนะนำรูปแบบการโทรกลับแทน

วิธีที่แนะนำสำหรับReact 16.2 และรุ่นก่อนหน้าคือการใช้รูปแบบการโทรกลับ:

<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 สำหรับการใช้โทรกลับ


แม้แต่การอ้างอิงแบบตอบกลับที่กำหนดรุ่นเก่าโดยใช้สตริงเหมือนด้านล่าง

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

เพื่อให้ได้องค์ประกอบเพียงแค่ทำ

var object = this.refs.Progress1;

จำไว้ว่าให้ใช้thisภายในบล็อกฟังก์ชั่นลูกศรเช่น:

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

และอื่น ๆ ...


5
Facebook แนะนำให้ใช้วิธีนี้ ดูที่นี่facebook.github.io/react/docs/refs-and-the-dom.html
Dmitry

4
@dmitrymar ตามที่ฉันเห็นหน้าข้างบนเขียนขึ้นสำหรับ v15.4.2 เป็นต้นไปและฉันเดาว่านี่ไม่ได้อยู่ที่นั่นก่อนหน้านี้เมื่อฉันเขียนคำตอบ Anyways แก้ไขคำตอบด้วยวิธีการที่ถูกต้อง
Shubham Khatri

2
@MattSidor ขอบคุณสำหรับการแก้ไขคุณช่วยฉันสักครู่ :-)
Shubham Khatri

อืมคำถามจะเกิดอะไรขึ้นถ้าฉันไม่สามารถเข้าถึงได้ผ่าน "นี่" เช่นถ้าองค์ประกอบที่ฉันต้องการเป็นตัวอย่างของคลาสอื่น? (เช่นเด็กอีกคนตอบสนององค์ประกอบภายในองค์ประกอบหลัก)
akshay

@akshaykishore คุณจะต้องผ่านการอ้างอิงโดยใช้ชื่ออื่นที่เรียกว่า innerRef และส่งไปยังองค์ประกอบที่ต้องการ
Shubham Khatri

37

เพื่อให้ได้องค์ประกอบในreactคุณจำเป็นต้องใช้refและภายในฟังก์ชั่นที่คุณสามารถใช้ReactDOM.findDOMNodeวิธีการ

แต่สิ่งที่ฉันชอบทำมากกว่าคือโทรหาผู้อ้างอิงในงาน

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

นี่คือลิงค์ที่ดีที่จะช่วยคุณค้นหา


2
นี่เป็นวิธีที่ถูกต้องในการทำเช่นนี้ นี่เป็นการเพิ่มการอ้างอิงไปยังองค์ประกอบบนวัตถุ / คลาสที่คุณสามารถใช้this.myTextInputเพื่อเข้าถึง
Sam Parmenter

1
ฉันจะทำสิ่งนี้กับองค์ประกอบที่สร้างขึ้นแบบไดนามิกได้อย่างไร
Sagar Kodte

การโทรReact.findDOMNodeให้ฉันreact__WEBPACK_IMPORTED_MODULE_0___default.a.findDOMNode is not a function
James Poulose

@JamesPoulose ตรวจสอบให้แน่ใจว่าคุณไม่ได้ทำงานในโหมดเข้มงวดเนื่องจากการตอบสนองจะไม่อนุญาตให้คุณใช้งานReact.findDOMNodeในโหมดเข้มงวด
Limpuls

13

คุณสามารถแทนที่

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

กับ

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


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

3
ฉันจะทำสิ่งนี้กับองค์ประกอบที่สร้างขึ้นแบบไดนามิกได้อย่างไร
Sagar Kodte

1

เนื่องจาก React ใช้รหัส JSX เพื่อสร้าง HTML เราไม่สามารถอ้างอิง dom โดยใช้วิธีการควบคุมเช่น documment.querySelector หรือ getElementById

แต่เราสามารถใช้ระบบ Ref React เพื่อเข้าถึงและจัดการ Dom ดังแสดงในตัวอย่างด้านล่าง:

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
นี่ไม่เป็นความจริง. คุณสามารถเพิ่มรหัสลงในองค์ประกอบ img คว้ามันโดยใช้ document.getElementById และในกรณีส่วนใหญ่มันจะทำงานได้ดี มันอาจทำให้เกิดปัญหา / ทำให้รหัสของคุณยากขึ้นในการแก้ปัญหา แต่ตอบสนอง / jsx donlt ทำให้มันเป็นเช่นนั้นเพื่อให้คุณลาดเทใช้วิธีการ Dom พื้นเมือง
adam tropp
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.