React: Can't call prop function when it is inside of another function?

杀马特。学长 韩版系。学妹 提交于 2021-02-08 16:54:37

问题


I am trying to move over the Auth0 login function as described in their tutorial. I am able to get it work if I use it like this:

<button className="btn" onClick={this.props.route.auth.login.bind(this)}>test</button>

but if I set up the button to call a function I define above the render function like this:

  login() {
   this.props.route.auth.login.bind(this);
  }

And change the onclick to be like this:

onClick={this.login()}

or

onClick={() => this.login()}

Then the auth login modal never opens and i receive no error. Also i added a console.log to login() and I can see it in the console, but the actual login modal never opens? It works in the first example, but not in the others.

The reason I am attempting to move this into a function is because I would like to pass the login function down into a child component later, and I was unable to do so and I believe this to be the root issue thats preventing me.


回答1:


bind does not call your function:

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. docs

Also, you are setting the value of onClick prop to the return value of login. If you want to pass a reference to the function, you have to do it without the ().

Your code should look like this:

<button className="btn" onClick={() => this.login()}>test</button> <!-- You need to keep a reference to `this`, hence the binding -->

Then:

login() {
   this.props.route.auth.login();
}

I edited the answer so that it uses an arrow function. However, I prefer not doing that, since it makes the code a bit cumbersome, and rather bind all the functions in the constructor, like @patrick-w-mcmahon did.




回答2:


Let's say you have a container MyContainer and this container renders a view called MyView. This view has a button that calls a method. MyContainer is going to pass to the MyView the method it needs to use.

MyContainer:

class MyContainer extends React.Component {
 constructor(props) {
  super(props);
  this.myFunc = this.myFunc.bind(this);
 }

 myFunc() {
  console.log("hello world");
 }

 render() {
  return <MyView myClick={this.myFunc}/>;
 }
}

MyView:

const MyView = ({ myClick }) => {
  return <button onClick={myClick} />;
};

MyView.propTypes = {
  myClick: PropTypes.func
};

export default MyView;

You pass the needed function from the container to the view and the view calls its parents function from props. the use of bind() sets this scope to the current scope so that when you call this from a different scope it is going to be the scope of the bind. When you are in the render you run a different scope so you must bind your functions to the current class scope so that this.myReallyCoolFunction() is pointing to the correct scope (your class scope).




回答3:


.bind() will only bind the object and arguments but won't call (run) the function.

TL;DR Just use .call() instead of .bind()

instead of .bind() you can use .call(this, args) which is basicaly the same as bind only that call will call (run) the function.

you could also use .apply(), which is basicaly the same as .call() but takes an array with the arguments instead of object like .call()

this way you can avoid arrow functions in you jsx render() and kind of keeping the line of thought with react.

something like ->

  login() {
   this.props.route.auth.login.call(this);
  }

When you call props function through return(JSX) React takes care of calling it once propagation ends.



来源:https://stackoverflow.com/questions/40769724/react-cant-call-prop-function-when-it-is-inside-of-another-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!