这是我的代码:
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中选择特定元素?
#1 楼
您可以通过指定ref
来做到这一点:在带有功能组件的react v16.8.0中,可以使用useRef定义引用。请注意,当您在功能组件上指定引用时,需要在其上使用React.forwardRef将该引用转发到使用useImperativeHandle
的DOM元素,以从功能组件中公开某些功能例如:
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;
DOC以使用React.createRef()
编辑
然而,facebook建议不要这样做,因为字符串引用存在一些问题,被认为是旧问题,并且很可能在将来的发行版中被删除。
来自文档:
旧版API:字符串引用
如果您以前使用过React,那么您可能会
熟悉较旧的API,其中ref属性是字符串,例如
“ textInput”,并且DOM节点作为this.refs.textInput访问。我们
建议不要这样做,因为字符串引用存在一些问题,被视为
遗留问题,并且很可能在将来的发行版中删除。如果
您当前正在使用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定义的ref都使用类似字符串的字符串下面
<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;
}
等等...
#2 楼
要在react
中获取元素,您需要使用ref
,并且在函数内部可以使用ReactDOM.findDOMNode
方法。但是我想做的更多的是在事件内部调用ref
<input type="text" ref={ref => this.myTextInput = ref} />
这是一个很好的链接,可以帮助您找出答案。
评论
这是正确的方法。这将添加对对象/类上元素的引用,您可以仅使用this.myTextInput进行访问。
– Sam Parmenter
17年2月12日在10:42
如何使用动态创建的元素执行此操作?
– Sagar Kodte
19-09-17在13:12
调用React.findDOMNode给了我react__WEBPACK_IMPORTED_MODULE_0 ___ default.a.findDOMNode不是一个函数
–詹姆斯·普洛斯(James Poulose)
2月23日4:19
@JamesPoulose确保您未在严格模式下运行,因为React不允许您在严格模式下使用React.findDOMNode。
–Limpuls
3月8日23:15
#3 楼
您可以将document.getElementById(this.state.baction).addPrecent(10);
替换为
this.refs[this.state.baction].addPrecent(10);
<Progressbar completed={25} ref="Progress1" id="Progress1"/>
评论
如何使用动态创建的元素执行此操作?
– Sagar Kodte
19-09-17在13:12
#4 楼
由于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}
/>
);
}
}
评论
这不是真的。您可以将一个id添加到img元素,使用document.getElementById来获取它,并且在大多数情况下,它可以正常工作。它可能会导致问题/使您的代码难以调试,但react / jsx donlt使其无法使用,因此您无法使用本机Dom方法
– adam tropp
1月22日13:44
评论
Facebook建议不要采用这种方法。看到这里facebook.github.io/react/docs/refs-and-the-dom.html
–德米特里
17年2月10日在16:18
@dmitrymar正如我所见,上面的页面是为v15.4.2及更高版本编写的,我想,我早在撰写答案时就没有。无论如何,用正确的方法编辑了答案
–Shubham Khatri
17年2月13日在3:56
@MattSidor,感谢您的编辑,您为我节省了一些时间:-)
–Shubham Khatri
18年4月19日在5:32
嗯,问我是否不能通过“ this”访问它,例如,如果我需要的组件是另一个类的实例怎么办? (即,父组件中的另一个子反应组件)
–akshay kishore
19年5月13日在11:53
@akshaykishore您需要使用另一个名称(innerRef)将ref向下传递,并将其传递给所需的组件
–Shubham Khatri
19年5月13日在12:26