-
Notifications
You must be signed in to change notification settings - Fork 47k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Binding in react #7385
Comments
This bug tracker is for issues with react itself. For usage questions, please ask on StackOverflow or IRC. The only solution that comes to mind is some kind of memoization, but there are a lot of ways to do it with different trade offs. In some cases the memoization could be more expensive than the child rerendering. |
I'm not use if it'll prevent unnecessary rerenders. Can you test and send me feedback? // Using stateful components
class Something extends React.Component {
constructor () {
super()
this.doSomething = this.doSomething.bind(this)
}
doSomething (take, take2) {
return event => {
event.preventDefault()
return take + take2
};
}
render () {
return (
<div>
<button onClick={this.doSomething(5, 6)}>clickMe!</button>
</div>
);
}
}
// Define this outside Something()
function doSomething (take, take2) {
return event => {
event.preventDefault()
return take + take2
};
}
// Using stateless components
function Something (props) {
return (
<div>
<button onClick={doSomething(5, 6)}>clickMe!</button>
</div>
);
} |
Yeah, the issue is that you're invoking your method, not passing it down. You can also pass arguments to this.doSomething = this.doSomething.bind(this, 5, 6) If you have access to the arguments for <button onClick={this.doSomething}>clickMe!</button>
@hnordt your method won't prevent unnecessary renders because you're still returning a new function very time the component is rendered. |
Or just use arrow functions.
|
@milesj that would still mean that the |
Re-creating functions in It’s not always applicable, and you should measure and test if it makes a difference. Using arrows (or even So if you don’t use |
If you really know that binding was expensive in your case after measuring the performance before and after in your app, but you want to pass some arguments, you can just pass them as props: The benefits of this are dubious if |
@gaearon I ask not only because I think its a performance hit to my app at all. I ask because if there is a "better" way or more efficient way of doing things because I am using It's kind of like the issue going around on twitter where you have developers passing all the props using rest. rather than passing down whats needed. Both work just one is preferred so that it is explicit what is needed. I view it like this. I rather do it right the first time around not because the other way is wrong but because I think it might be beneficial in the slightest way. |
@timeche I thought the same. As the child component would need to call the function with the props in a handler as well? |
@gaearon Why not use the props directly in the Example: doSomething() {
return this.props.x + this.props.y
}
render() {
return <Comp doSomething={this.doSomething} />
} |
@timche I think presumably they would be different for each item in a list (that’s the usual use case) but I’m not sure because the example is too trivial. |
I think the "best" way is to write the code as naturally as you can, and if you have issues, you can optimize individual components. It won't be changing "a whole lot of code", most likely you'll need to tweak a few components for desired perf. Also in most apps you won't even have those issues to begin with. The funny thing with perf is there is no hard rule that you could just follow every time. We don't recommend making every single component use |
@sandysaders take a look here ;)
|
And no, you can’t do this with stateless functional components. So if you insist on never passing arrows down, you either won’t be able to pass callbacks down from stateless functional components. |
@sandysaders Btw, you can also use arrow functions in your classes with Example: class Something extends React.Component {
doSomething = (x, y) => x + y
render() {
return <Comp doSomething={this.doSomething} />
}
} |
We have been using html data attributes when every item of a list needs to know who it is. render () {
return (
<div>
this.props.items.map((item, index) => {
return <button data-index={index} onClick={this.onClick} />
})
</div>
)
}
onClick = ({target: {dataset: {index}}}) => {
alert(this.props.items[index])
} |
Reading from DOM is generally not very great if you already have this data provided by React. |
yep, i agree. the render () {
return (
<div>
this.props.items.map((item, index) => {
return <Button item={item} onClick={this.onClick} />
})
</div>
)
}
onClick = (item) => {
alert(item)
}
// Button.jsx
render () {
return <button onClick={this.onClick} />
}
onClick = (item) => {
const {item, onClick} = this.props
onClick(item)
} |
This article provided an way to pass arguments without bind. Perhaps it helps. |
@ErythroME I'd take that article with a grain of salt. The only truth is #2, in that Arrow functions are not inefficient -- this is exactly what their use case is for. If anything, it's the transpilation down to regular functions via babel that is the performance loss. Furthermore, don't use #4 or #6 as they're not finalized specs or are dead/denied specs. The best, easiest, and most idiomatic approach in my opinion is #5 (or the 2nd bonus). These should be the standard as it solves most, if not all of use cases. |
I recently read an article on Medium about binding in react. Basically explaining how you should bind functions inside of the constructor of stateful components to prevent unnecessary rerenders in a component. It shows how using arrow function and
.bind
causes function creation on the spot and makes it seem like new props are being received continuously even when it may not. This is bad and prevents optimizations according to the article. So great I know I should bind in constructor but what about binding methods with parameters not just calling them in stateful and stateless components?Say theres something like the following:
It throws an error because the call evaluates immediately to a number when it should be a function. This makes sense and the only way around this I've been able to go around this is using an arrow function in the
onClick
() => doSomething(5, 6)
and that will run. But this will cause unnecessary rerenders that the article explained. So how could you do this better and prevent unnecessary rerenders in stateless and stateful components?The text was updated successfully, but these errors were encountered: