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()
}
我想在切换时更新loopActive
状态,但在处理程序中未定义this
对象。根据教程文档,我this
应该引用该组件。我错过了什么吗?
答案 0 :(得分:150)
ES6 React.Component没有自动将方法绑定到自身。您需要在构造函数中自己绑定它们。像这样:
constructor (props){
super(props);
this.state = {
loopActive: false,
shuffleActive: false,
};
this.onToggleLoop = this.onToggleLoop.bind(this);
}
答案 1 :(得分:72)
有两种方法。
一个是补充
构造函数中的this.onToggleLoop = this.onToggleLoop.bind(this);
。
另一个是箭头功能
onToggleLoop = (event) => {...}
。
然后有onClick={this.onToggleLoop.bind(this)}
。
答案 2 :(得分:14)
以这种方式编写你的函数:
onToggleLoop = (event) => {
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
http://www.react.express/fat_arrow_functions
关键字的绑定在胖箭头函数的外部和内部是相同的。这与使用function声明的函数不同,函数可以在调用时将其绑定到另一个对象。维护此绑定对于映射等操作非常方便:this.items.map(x =&gt; this.doSomethingWith(x))。
答案 3 :(得分:9)
我在渲染函数中遇到了类似的绑定,最后以下列方式传递了this
的上下文:
{someList.map(function(listItem) {
// your code
}, this)}
我也用过:
{someList.map((listItem, index) =>
<div onClick={this.someFunction.bind(this, listItem)} />
)}
答案 4 :(得分:2)
您应该注意到this
取决于函数的调用方式
即:当函数被调用为对象的方法时,其this
设置为调用该方法的对象。
this
可作为组件对象在JSX上下文中访问,因此可以将内联方法调用为this
方法。
如果仅将引用传递给函数/方法,似乎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
答案 5 :(得分:1)
如果您正在使用babel,则可以使用ES7绑定运算符绑定“ this” https://babeljs.io/docs/en/babel-plugin-transform-function-bind#auto-self-binding
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>
)
}
}
答案 6 :(得分:0)
如果您在生命周期方法中调用您创建的方法,例如componentDidMount ...那么您只能使用this.onToggleLoop = this.onToogleLoop.bind(this)
和胖箭头函数onToggleLoop = (event) => {...}
。
在构造函数中声明函数的常规方法不会起作用,因为之前调用了生命周期方法。
答案 7 :(得分:0)
在我的情况下,这是解决方案 =()=> {}
git -c diff.indentHeuristic=true add -p
答案 8 :(得分:0)
对于我来说,对于使用forwardRef接收引用的无状态组件,我必须按照https://itnext.io/reusing-the-ref-from-forwardref-with-react-hooks-4ce9df693dd
的说明进行操作从此开始(onClick无权访问“ this”的等效内容)
const Com = forwardRef((props, ref) => {
return <input ref={ref} onClick={() => {console.log(ref.current} } />
})
对此(有效)
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} } />
})
答案 9 :(得分:0)
您可以重写如何从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>
);
}
React documentation在通过属性的表达式调用函数时显示了这种模式。