Javascript 反应:“this”在组件函数中未定义

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/33973648/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 15:44:14  来源:igfitidea点击:

React: "this" is undefined inside a component function

javascriptreactjsthis

提问by Maximus S

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 loopActivestate on toggle, but thisobject is undefined in the handler. According to the tutorial doc, I thisshould refer to the component. Am I missing something?

我想loopActive在切换时更新状态,但this处理程序中未定义对象。根据教程文档,我this应该参考组件。我错过了什么吗?

回答by Ivan

ES6 React.Component doesn't auto bind methods to itself. You need to bind them yourself in constructor. Like this:

ES6 React.Component 不会自动将方法绑定到自身。您需要自己在构造函数中绑定它们。像这样:

constructor (props){
  super(props);

  this.state = {
      loopActive: false,
      shuffleActive: false,
    };

  this.onToggleLoop = this.onToggleLoop.bind(this);

}

回答by J. Mark Stevens

There are a couple of ways.

有几种方法。

One is to add this.onToggleLoop = this.onToggleLoop.bind(this);in the constructor.

一种是this.onToggleLoop = this.onToggleLoop.bind(this);在构造函数中添加 。

Another is arrow functions onToggleLoop = (event) => {...}.

另一个是箭头函数 onToggleLoop = (event) => {...}

And then there is onClick={this.onToggleLoop.bind(this)}.

然后是onClick={this.onToggleLoop.bind(this)}

回答by ShaTin

Write your function this way:

这样写你的函数:

onToggleLoop = (event) => {
    this.setState({loopActive: !this.state.loopActive})
    this.props.onToggleLoop()
}

Fat Arrow Functions

粗箭头函数

the binding for the keyword this is the same outside and inside the fat arrow function. This is different than functions declared with function, which can bind this to another object upon invocation. Maintaining the this binding is very convenient for operations like mapping: this.items.map(x => this.doSomethingWith(x)).

关键字 this 的绑定在胖箭头函数的外部和内部是相同的。这与使用 function 声明的函数不同,后者可以在调用时将 this 绑定到另一个对象。维护 this 绑定对于映射之类的操作非常方便:this.items.map(x => this.doSomethingWith(x))。

回答by duhaime

I ran into a similar bind in a render function and ended up passing the context of thisin 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)} />
)}

回答by Jakub Kutrzeba

You should notice that thisdepends on how function is invoked ie: when a function is called as a method of an object, its thisis set to the object the method is called on.

您应该注意到这this取决于函数的调用方式,即:当一个函数作为this对象的方法被调用时,它被设置为调用该方法的对象。

thisis accessible in JSX context as your component object, so you can call your desired method inline as thismethod.

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

回答by Henry Jacob

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,则使用 E​​S7 绑定运算符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>
    )
  }

}

回答by Alex

in my case this was the solution = () => {}

就我而言,这是解决方案= () => {}

methodName = (params) => {
//your code here with this.something
}

回答by GWorking

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} } />
})

回答by Guchelkaben

If you call your created methodin 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...)中调用您创建的方法,那么您只能使用 thethis.onToggleLoop = this.onToogleLoop.bind(this)和 fat arrow function onToggleLoop = (event) => {...}

The normal approach of the declaration of a function in the constructor wont work because the lifecycle methods are called earlier.

在构造函数中声明函数的正常方法将不起作用,因为生命周期方法被调用得更早。