如何在React中访问DOM元素?什么是React中document.getElementById()的等效项


202

如何在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中选择特定元素?

Answers:


213

您可以通过指定 ref

编辑:在带有功能组件的react v16.8.0中,可以使用useRef定义引用。请注意,当您在功能组件上指定引用时,需要在其上使用React.forwardRef将该引用转发到use的DOM元素,useImperativeHandle以从功能组件中公开某些功能

例如:

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

编辑:

React 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;

使用React.createRef()的DOC


编辑

但是,facebook建议不要这样做,因为字符串引用存在一些问题,被认为是旧问题,并且很可能在将来的发行版中被删除。

从文档:

旧版API:字符串引用

如果您以前使用过React,那么您可能会熟悉一个较旧的API,其中ref属性是一个字符串,例如“ textInput”,并且可以通过this.refs.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使用回调


甚至旧版本的react定义的引用都使用如下字符串

<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及更高版本编写的,我想这是我撰写答案时更早的版本。无论如何,使用正确的方法编辑了答案
Shubham Khatri

2
@MattSidor,感谢您的编辑,您为我节省了一些时间:-)
Shubham Khatri

嗯,问我是否不能通过“ this”访问它,例如,如果我需要的组件是另一个类的实例怎么办?(即父组件中的另一个子组件)
Akshay kishore

@akshaykishore您将需要使用另一个名称“ innerRef”将引用向下传递,并将其传递给所需的组件
Shubham Khatri

37

用于获取元素react,你需要使用ref和函数内可以使用ReactDOM.findDOMNode的方法。

但是我想做的更多的是在事件内部调用ref

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

这是一个很好的链接,可以帮助您找出答案。


2
这是执行此操作的正确方法。这将添加对对象/类上元素的引用,您可以简单地使用该引用this.myTextInput进行访问。
山姆·帕门特

1
如何使用动态创建的元素执行此操作?
萨加尔·科德

打电话React.findDOMNode给了我react__WEBPACK_IMPORTED_MODULE_0___default.a.findDOMNode is not a function
James Poulose

@JamesPoulose确保您未在​​严格模式下运行,因为react不允许您React.findDOMNode在严格模式下使用。
Limpuls

12

您可以更换

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

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


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

3
如何使用动态创建的元素执行此操作?
萨加尔·科德

1

由于React使用JSX代码创建HTML,因此我们无法使用documment.querySelector或getElementById之类的调节方法来引用dom。

相反,我们可以使用React ref系统访问和操作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
这不是真的。您可以将一个id添加到img元素,使用document.getElementById来获取它,并且在大多数情况下,它将正常工作。这可能会导致问题/使你的代码难以调试,但反应/ JSX donlt让这个你不能使用本地DOM方法
亚当tropp
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.