我有一个React组件,我想在点击时切换一个css类。
所以我有这个:
export class myComponent extends React.Component {
constructor() {
super();
this.state = { clicked: false };
this.handleClick = this.handleClick.bind(this);
}
render() {
return (
<div>
<div onClick={this.clicked}><span ref="btn" className="glyphicon"> </span></div>
</div>
);
}
handleClick() {
this.refs.btn.classList.toggle('active');
}
componentDidMount() {
this.refs.btn.addEventListener('click', this.handleClick);
this.setState({
clicked: this.state.clicked = true,
});
}
componentWillUnmount() {
this.refs.btn.removeEventListener('click', this.handleClick);
this.setState({
clicked: this.state.clicked = false,
});
}
}
这个问题是ESLint一直告诉我&#34; this.refs&#34;折旧。
我该怎么做?如何修复它以免它使用折旧代码?
答案 0 :(得分:41)
您所指的Lint规则称为no-string-refs,并通过以下方式向您发出警告:
"Using string literals in ref attributes is deprecated (react/no-string-refs)"
您收到此警告是因为已实施使用refs
的弃用方法(通过使用字符串)。根据您的React版本,您可以执行以下操作:
constructor() {
super();
this.btnRef= React.createRef();
this.state = { clicked: false };
this.handleClick = this.handleClick.bind(this);
}
render() {
return (
<div>
<div onClick={this.addVote}><span ref={this.btnRef} className="glyphicon"> </span></div>
</div>
);
}
constructor() {
super();
this.btnRef; //not necessary to declare the variable here, but I like to make it more visible.
this.state = { clicked: false };
this.handleClick = this.handleClick.bind(this);
}
render() {
return (
<div>
<div onClick={this.addVote}><span ref={(el) => this.btnRef = el} className="glyphicon"> </span></div>
</div>
);
}
为了更好的可读性,你也可以这样做:
render() {
let myRef = (el) => this.btnRef = el;
return (
<div>
<div onClick={this.addVote}><span ref={myRef} className="glyphicon"> </span></div>
</div>
);
}
查看官方文档在Refs and the DOM上所说的内容,特别是this section:
旧版API:字符串引用
如果您之前使用过React,那么您可能会 熟悉较旧的API,其中
ref
属性是一个字符串,如"textInput"
,DOM节点作为this.refs.textInput
访问。我们 建议反对它,因为字符串引用有some issues,被认为是 旧版和可能会在以后的某个版本中删除。如果 您目前正在使用this.refs.textInput
来访问裁判,我们 建议使用回调模式。
答案 1 :(得分:0)
你可以尝试一种更具声明性的方式。我更改了您的代码以反映这一点。您只需要提醒一个组件将在每个州/道具更改时刷新并调用渲染。因此,我们可以在render方法中创建元素的类。
import React from 'react'
export default class myComponent extends React.Component {
constructor() {
super();
this.state = { clicked: false };
this.handleClick = this.handleClick.bind(this);
}
render() {
let btnClass = 'glyphicon'
if(this.state.clicked){
btnClass+=' active'
}
return (
<div>
<div onClick={this.handleClick}><span ref="btn" className={btnClass}> </span></div>
</div>
);
}
handleClick() {
this.setState({
clicked: !this.state.clicked
})
}
}
答案 2 :(得分:0)
存在此ESLint规则的原因是字符串Ref即将退出。但是,对于上面的代码,我建议首先不要使用Ref。
React的优势在于它是声明性的。意思是,我们有一个状态和一个表达式(返回的JSX),该表达式表示在给定特定状态下UI(更确切地说是DOM)的外观。
仅使用状态和UI表达式可以完成的任何操作,都应以这种方式完成。在上面的代码中使用Ref的问题在于,使代码变得势在必行。我们仅从JSX中就无法理解DOM的外观。您可以通过以下方法以声明的方式获得相同的结果:
export class myComponent extends React.Component {
constructor(props) {
super(props);
this.state = {
active: false
};
}
handleClick = () => { // with arrow function there is no need for binding.
this.setState(
prevState => {
return {
active: !prevState.active
}
}
)
}
render() {
return (
<div>
<span
onClick={this.handleClick}
className={`glyphicon ${this.state.active && "active"}`}
>
Hello World
</span>
</div>
);
}
}
当状态和UI表达式不够用并且您需要访问实际DOM时,应使用引用。例如,专注于输入字段,滚动到元素或获取元素的确切宽度和高度。
字符串引用会损害性能,不可组合且无法解决。
字符串引用存在一些问题,被认为是旧问题,并且可能 在将来的版本之一中删除。 [官方React文档]
[resource1] [1],[resource2] [1]
选项1:使用React.createRef
class MyComponent extends Component {
constructor(props) {
super(props)
this.myRef = React.createRef() // create a ref object
}
render() {
return <div ref={this.myRef}></div> // Attach the ref property to a dom element
}
}
选项2:使用引用回调
class MyComponent extends Component {
constructor(props){ // Optional, declare a class field
super(props)
this.myRef=null
}
render() {
return <div ref={ (ref) => this.myRef=ref }></div>
} // Attach the dom element to a class field
}