提问人:Maximus S 提问时间:11/29/2015 最后编辑:Emile BergeronMaximus S 更新时间:4/12/2023 访问量:172073
React:“this”在组件函数中未定义
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()
}
我想在切换时更新状态,但处理程序中未定义对象。根据教程文档,我应该参考组件。我错过了什么吗?loopActive
this
this
答:
有几种方法。
一种是添加构造函数。this.onToggleLoop = this.onToggleLoop.bind(this);
另一个是箭头函数。onToggleLoop = (event) => {...}
然后是.onClick={this.onToggleLoop.bind(this)}
评论
onClick
shouldComponentUpdate
PureComponent
ES6 不会自动将方法绑定到自身。您需要自己将它们绑定在 .喜欢这个:React.Component
constructor
constructor (props){
super(props);
this.state = {
loopActive: false,
shuffleActive: false,
};
this.onToggleLoop = this.onToggleLoop.bind(this);
}
评论
() => this.onToggleLoop
this
this
我在渲染函数中遇到了类似的绑定,并最终以以下方式传递了上下文:this
{someList.map(function(listItem) {
// your code
}, this)}
我还使用过:
{someList.map((listItem, index) =>
<div onClick={this.someFunction.bind(this, listItem)} />
)}
评论
如果在生命周期中调用创建的方法,则 componentDidMount...那么你就只能使用 和 胖箭头函数了。this.onToggleLoop = this.onToogleLoop.bind(this)
onToggleLoop = (event) => {...}
在构造函数中声明函数的正常方法将不起作用,因为生命周期方法被提前调用。
这样编写函数:
onToggleLoop = (event) => {
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
关键字 this 的绑定在 FAT 箭头函数的外部和内部是相同的。这与使用 function 声明的函数不同,后者可以在调用时将其绑定到另一个对象。维护 this 绑定对于映射等操作非常方便:this.items.map(x => this.doSomethingWith(x))。
评论
ReferenceError: fields are not currently supported
如果你使用的是 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>
)
}
}
您应该注意到,这取决于函数的调用方式
即:当函数作为对象的方法调用时,它被设置为调用该方法的对象。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
评论
onClick={this.onToggleLoop}
onToggleLoop = () => /*body using 'this'*/
就我而言,这就是解决方案= () => {}
methodName = (params) => {
//your code here with this.something
}
评论
就我而言,对于使用 forwardRef 接收 ref 的无状态组件,我必须按照此处所说的执行操作 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} } />
})
您可以从 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 文档在从属性中的表达式调用函数时展示了这种模式。
我想解释一下为什么是未定义的:
如果我们在一个不是箭头函数的函数中使用,那么在不处于严格模式时会绑定到一个全局对象。但是使用严格模式,将是未定义的(https://www.w3schools.com/js/js_this.asp)。this
this
this
this
并且 ES6 模块始终处于严格模式(javascript:在模块内部不需要使用严格)。
您可以在函数中使用构造函数中的方法与组件的实例绑定:this
onToggleLoop
PlayerControls
bind
constructor(props) {
super(props)
this.state = {
loopActive: false,
shuffleActive: false,
}
this.onToggleLoop = this.onToggleLoop.bind(this)
}
或者改用箭头函数:
onToggleLoop = (event) => {
this.setState({loopActive: !this.state.loopActive})
this.props.onToggleLoop()
}
箭头函数没有上下文,因此在箭头函数中将表示定义箭头函数的对象。this
评论
我最近遇到了“这是未定义的”错误,以下方法对我有用。我将状态传递给我的类构造函数,并且只需将用作箭头函数的函数传递给我的侦听器。
const cartUtils: CartUtils = new CartUtils(cartItems, setCartItems);
onClick={(evt) => cartUtils.getProductInfo(evt)}
评论