[英]React: "this" is undefined inside a component function
class PlayerControls extends React.Component {
constructor(props) {
super(props)
this.state = {
loopActive: false,
shuffleActive: false,
}
}
render() {
var shuffleClassName = this.state.toggleActive ? "player-control-icon active" : "player-control-icon"
return (
<div className="player-controls">
<FontAwesome
className="player-control-icon"
name='refresh'
onClick={this.onToggleLoop}
spin={this.state.loopActive}
/>
<FontAwesome
className={shuffleClassName}
name='random'
onClick={this.onToggleShuffle}
/>
</div>
);
}
onToggleLoop(event) {
// "this is undefined??" <--- here
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
I want to update loopActive
state on toggle, but this
object is undefined in the handler.我想在切换时更新
loopActive
状态,但this
对象在处理程序中未定义。 According to the tutorial doc, I this
should refer to the component.根据教程文档,我
this
应该是指组件。 Am I missing something?我错过了什么吗?
ES6 React.Component
doesn't auto bind methods to itself. ES6
React.Component
不会自动将方法绑定到自身。 You need to bind them yourself in constructor
.您需要自己在
constructor
绑定它们。 Like this:像这样:
constructor (props){
super(props);
this.state = {
loopActive: false,
shuffleActive: false,
};
this.onToggleLoop = this.onToggleLoop.bind(this);
}
There are a couple of ways.有几种方法。
One is to add this.onToggleLoop = this.onToggleLoop.bind(this);
一种是添加
this.onToggleLoop = this.onToggleLoop.bind(this);
in the constructor.在构造函数中。
Another is arrow functions onToggleLoop = (event) => {...}
.另一个是箭头函数
onToggleLoop = (event) => {...}
。
And then there is onClick={this.onToggleLoop.bind(this)}
.然后是
onClick={this.onToggleLoop.bind(this)}
。
Write your function this way:这样写你的函数:
onToggleLoop = (event) => {
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
the binding for the keyword this is the same outside and inside the fat arrow function.
关键字 this 的绑定在胖箭头函数的外部和内部是相同的。 This is different than functions declared with function, which can bind this to another object upon invocation.
这与使用 function 声明的函数不同,后者可以在调用时将 this 绑定到另一个对象。 Maintaining the this binding is very convenient for operations like mapping: this.items.map(x => this.doSomethingWith(x)).
维护 this 绑定对于映射之类的操作非常方便:this.items.map(x => this.doSomethingWith(x))。
I ran into a similar bind in a render function and ended up passing the context of this
in the following way:我在渲染函数中遇到了类似的绑定,最终以下列方式传递了
this
的上下文:
{someList.map(function(listItem) {
// your code
}, this)}
I've also used:我也用过:
{someList.map((listItem, index) =>
<div onClick={this.someFunction.bind(this, listItem)} />
)}
You should notice that this
depends on how function is invoked ie: when a function is called as a method of an object, its this
is set to the object the method is called on.您应该注意到
this
取决于函数的调用方式,即:当一个函数作为对象的方法被调用时,它的this
被设置为调用该方法的对象。
this
is accessible in JSX context as your component object, so you can call your desired method inline as this
method. this
可以作为组件对象在 JSX 上下文中访问,因此您可以将所需的方法内联调用this
方法。
If you just pass reference to function/method, it seems that react will invoke it as independent function.如果您只是传递对函数/方法的引用,则 react 似乎会将其作为独立函数调用。
onClick={this.onToggleLoop} // Here you just passing reference, React will invoke it as independent function and this will be undefined
onClick={()=>this.onToggleLoop()} // Here you invoking your desired function as method of this, and this in that function will be set to object from that function is called ie: your component object
If you are using babel, you bind 'this' using ES7 bind operator https://babeljs.io/docs/en/babel-plugin-transform-function-bind#auto-self-binding如果您使用 babel,则使用 ES7 绑定运算符https://babeljs.io/docs/en/babel-plugin-transform-function-bind#auto-self-binding绑定“this”
export default class SignupPage extends React.Component {
constructor(props) {
super(props);
}
handleSubmit(e) {
e.preventDefault();
const data = {
email: this.refs.email.value,
}
}
render() {
const {errors} = this.props;
return (
<div className="view-container registrations new">
<main>
<form id="sign_up_form" onSubmit={::this.handleSubmit}>
<div className="field">
<input ref="email" id="user_email" type="email" placeholder="Email" />
</div>
<div className="field">
<input ref="password" id="user_password" type="new-password" placeholder="Password" />
</div>
<button type="submit">Sign up</button>
</form>
</main>
</div>
)
}
}
in my case this was the solution = () => {}就我而言,这是解决方案= () => {}
methodName = (params) => {
//your code here with this.something
}
If you call your created method in the lifecycle methods like componentDidMount... then you can only use the this.onToggleLoop = this.onToogleLoop.bind(this)
and the fat arrow function onToggleLoop = (event) => {...}
.如果你在生命周期方法中调用你创建的方法,比如 componentDidMount... 那么你只能使用
this.onToggleLoop = this.onToogleLoop.bind(this)
和this.onToggleLoop = this.onToogleLoop.bind(this)
箭头函数onToggleLoop = (event) => {...}
.
The normal approach of the declaration of a function in the constructor wont work because the lifecycle methods are called earlier.在构造函数中声明函数的正常方法将不起作用,因为生命周期方法被调用得更早。
In my case, for a stateless component that received the ref with forwardRef, I had to do what it is said here https://itnext.io/reusing-the-ref-from-forwardref-with-react-hooks-4ce9df693dd就我而言,对于接收带有 forwardRef 的 ref 的无状态组件,我必须按照此处所说的进行操作https://itnext.io/reusing-the-ref-from-forwardref-with-react-hooks-4ce9df693dd
From this (onClick doesn't have access to the equivalent of 'this')从此(onClick 无法访问等效于“this”的内容)
const Com = forwardRef((props, ref) => {
return <input ref={ref} onClick={() => {console.log(ref.current} } />
})
To this (it works)对此(它有效)
const useCombinedRefs = (...refs) => {
const targetRef = React.useRef()
useEffect(() => {
refs.forEach(ref => {
if (!ref) return
if (typeof ref === 'function') ref(targetRef.current)
else ref.current = targetRef.current
})
}, [refs])
return targetRef
}
const Com = forwardRef((props, ref) => {
const innerRef = useRef()
const combinedRef = useCombinedRefs(ref, innerRef)
return <input ref={combinedRef } onClick={() => {console.log(combinedRef .current} } />
})
You can rewrite how your onToggleLoop method is called from your render() method.您可以重写如何从 render() 方法调用 onToggleLoop 方法。
render() {
var shuffleClassName = this.state.toggleActive ? "player-control-icon active" : "player-control-icon"
return (
<div className="player-controls">
<FontAwesome
className="player-control-icon"
name='refresh'
onClick={(event) => this.onToggleLoop(event)}
spin={this.state.loopActive}
/>
</div>
);
}
The React documentation shows this pattern in making calls to functions from expressions in attributes. React 文档显示了从属性中的表达式调用函数的这种模式。
I want to give an explanation why this
is undefined:我想解释一下为什么
this
是未定义的:
If we use this
in a function that is not an arrow function, this
is bound to a global object when not in strict mode.如果我们在非箭头函数的函数中使用
this
,则this
在非严格模式下绑定到全局对象。 But with strict mode, this
will be undefined ( https://www.w3schools.com/js/js_this.asp ).但是在严格模式下,
this
将是未定义的( https://www.w3schools.com/js/js_this.asp )。
And ES6 modules are always in strict mode ( javascript: use strict is unnecessary inside of modules ).并且 ES6 模块始终处于严格模式( javascript: use strict 在模块内部是不必要的)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.