React:哪个是推荐的箭头或正常功能? [英] React: Which is recommended arrow or normal function?

查看:28
本文介绍了React:哪个是推荐的箭头或正常功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我觉得进行手动函数/对象绑定和作用域相关问题令人头疼之后,我开始使用箭头函数,但最近我开始知道使用普通函数(ES5)比使用箭头函数(ES6)更好.

我对这些功能的理解

React 中的普通函数:

<块引用>

  1. 手动绑定对象/函数,以便在函数内部使用 state 或 props 并避免与作用域相关的问题
  2. 总是在构造函数中绑定对象/函数,而不是直接在渲染中绑定
  3. 如果你在构造函数中这样做,那么当你的组件第一次渲染时,Webpack 只会在 bundle.js 文件中创建一次新的对象/函数
  4. 如果你直接在渲染中执行,那么每次你的组件渲染和重新渲染时,Webpack 都会在 bundle.js 文件中创建一个新的对象/函数
  5. 如果不绑定,则无法访问状态或道具.您必须将当前对象分配给局部变量,否则 this.state 或 this.props 未定义

React 中的箭头函数:

<块引用>

  1. 无需在构造函数中绑定对象/函数,也无需渲染
  2. 您无需依赖当前对象的局部变量,即让 that = this;
  3. 您不会遇到范围问题,对象/函数绑定会自动执行

但我的疑问是我听说建议使用普通函数并将其绑定在构造函数中而不是使用箭头函数,因为每次组件渲染时,箭头函数都会在 Webpack bundle.js 中创建新的对象/函数 &重新渲染.

<块引用>

这是真的吗?推荐哪个?

该线程接受了答案在 React 中正确使用箭头函数说 —> 这取决于您使用箭头函数的确切位置.如果在 render 方法中使用 Arrow 函数,那么它们会在每次调用 render 时创建一个新实例,就像 bind 的工作方式一样.

对不起,如果你觉得这是一个戏剧性的问题,但这是我最大的疑问.请推荐

解决方案

那里有很多答案,但人们总是感到困惑.我知道这一点是因为我不久前感到困惑.过了一段时间,我掌握了概念.

<块引用>

  1. 手动绑定对象/函数以使用状态或道具在函数内部并避免与作用域相关的问题

不完全正确.您不需要绑定函数来使用 state 或 props.当您在作用域中丢失 this 上下文时,您将函数绑定到 this.例如在回调函数中.

class App 扩展 React.Component {状态 = {名称: "foo",}aFunction() {console.log( this.state.name );}使成为() {返回<div>{this.aFunction()}</div>;}}

你不需要绑定你的函数,因为 this 指向你的类并且你不会丢失它的上下文.但是如果你像按钮一样在回调中使用你的函数,你必须绑定它:

class App 扩展 React.Component {状态 = {名称: "foo",}aFunction() {console.log( this.state.name );}使成为() {返回 (<div><button onClick={this.aFunction}>点击</button>

);}}

这不起作用,因为您丢失了上下文.现在,您需要以某种方式恢复其上下文,对吗?好的,让我们看看如何做到这一点.首先,我想在按钮回调中绑定它.

是的,这有效.但是,它将在每次渲染中重新创建.所以:

<块引用>

  1. 总是在构造函数中绑定对象/函数,而不是直接在渲染中绑定

是的.不要像我上面那样绑定它,在你的构造函数中进行.

<块引用>

  1. 如果你在构造函数中这样做,那么当你的组件第一次渲染

  2. 如果你直接在渲染中做,那么每次你的组件渲染时,Webpack 都会在 bundle.js 文件中创建一个新的对象/函数并重新渲染

您在这里总结了我迄今为止试图解释的内容.但是,我认为 Webpack 不是这样做的,您的应用程序是.

<块引用>

  1. 如果不绑定,则无法访问状态或道具.您必须将当前对象分配给局部变量,否则 this.state 或this.props 未定义

同样,如果你在你的类范围内使用你的函数,你不必绑定它.如果你在你的类之外使用这个函数,比如按钮回调,你必须绑定它.这与 stateprops 无关.这与使用this有关.

您的第二个绑定选项是使用常规函数在构造函数中进行绑定,第三个选项是使用不绑定的箭头函数.

现在,箭头函数.

<块引用>

1.无需在构造函数中绑定对象/函数,也无需渲染

是的.

<块引用>

  1. 您无需依赖当前对象的局部变量,即让 that = this;

是的.

<块引用>

  1. 您不会遇到范围问题,对象/函数绑定会自动执行

是的.

<块引用>

但是我的疑问是听说建议用普通的函数并将其绑定在构造函数中而不是使用箭头函数因为箭头函数在 Webpack 中创建了新的对象/函数bundle.js 每次你的组件呈现 &重新渲染.

就像大家说的,这取决于你在哪里使用它们.

render() {返回 (<div><button onClick={() =>this.aFunction()}>点击</button>

);}

在这里,它将在每次渲染中重新创建.但是如果你不需要给它传递任何参数,你可以通过引用来使用它.

render() {返回 (<div><button onClick={this.aFunction}>点击</button>

);}

这和上一个一样.因此,如果您在渲染方法中看到 () ,则该函数会在每次渲染中重新创建.常规或箭头一个,都没有关系.如果您以某种方式调用它,那么您就是在重新创建它.这适用于渲染中的绑定,如 aFunction.bind(this).我在那里看到 ().

因此,通过引用使用函数可以避免此问题.现在,最大的问题是当我们需要一些参数时会发生什么?如果您使用箭头函数传递参数,请尝试更改您的逻辑.

但这真的那么重要吗?就像@Eric Kim 所说的那样,如果你真的需要优化,优化是一个问题.这是一个普遍的建议,因为我从很多人那里听到了这个建议.但就我个人而言,如果函数会在每次渲染中重新创建,我会尽量避免使用它们.但同样,这完全是个人的.

你怎么能改变你的逻辑?您正在使用项目映射数组并创建一个按钮.在此按钮中,您使用的是将项目名称传递给函数的函数.

<代码>{items.map( item =><button onClick={() =>this.aFunction(item.name)}>点击</button>)}

此函数将在每个项目的每次渲染中重新创建!所以,改变你的逻辑,创建一个单独的 Item 组件并映射它.将 item, aFunction 作为 props 传递.然后通过这个组件中的处理函数使用你的函数.

const Item = ( props ) =>{const handleClick = () =>props.aFunction( props.item.name );返回 (<button onClick={handleClick}>点击</button>);}

在这里,您使用的是带有引用的 onClick 处理程序,它会调用您的实际函数.不会在每次渲染中重新创建任何功能.但是,不利的一面是,您需要编写一个单独的组件和更多的代码.

您可以在大多数情况下应用此逻辑.也许会有一些你做不到的例子,谁知道呢.所以决定权在你.

顺便说一下,@widged 在评论中给出的 Medium 帖子是关于这个问题的著名讨论.箭头函数真的比普通函数慢吗?是的.但是多少钱?我猜没有那么多.此外,对于转译的代码也是如此.将来当他们成为本地人时,他们将成为更快的人.

作为个人旁注.自从我喜欢它们以来,我一直在使用箭头函数.但是前段时间在讨论中,有人说

<块引用>

当我在课堂上看到一个箭头函数时,我认为:'这个函数正在该课程之外使用/调用".如果我看到一个普通的我理解这个函数是在类内部调用的.

我真的很喜欢这种方法,现在如果我不需要在课外调用我的函数,我会使用常规方法.

I started using arrow functions after I felt doing manual function/object bindings and scope related issues are headache but very rencently I came to know that it’s better to use normal function(ES5) than arrow function(ES6).

My understanding about these functions

Normal function in React:

  1. Bind object/function manually in order to play with state or props inside the function and to avoid scope related issues
  2. Bind object/function always in constructor but not directly in render
  3. If you do it in constructor then Webpack creates new object/function in bundle.js file only once when your component renders for the first time
  4. If you do it directly in render then Webpack will create a new object/function in bundle.js file every time your component renders and re-renders
  5. If you don’t bind then you can’t access state or props. You have to assign current object to a local variable otherwise this.state or this.props is undefined

Arrow function in React:

  1. No need to bind an object/function in constructor nor render
  2. You no need to depend on local variable interms of current object i.e., let that = this;
  3. You will not have scope issues and object/function binding takes automatically

But my query is that I heard that it’s recommended to use normal function and bind it in constructor rather than using arrow function because arrow functions create new object/function in Webpack bundle.js every time your component renders & re-renders.

Is this true? Which is Recommended?

This thread accepted answer Correct use of arrow functions in React says —> It depends on where exactly are you using the Arrow function. If Arrow function are used in render method, then they creates a new instance everytime render is called just like how bind would work.

Sorry if you feel it’s a theatrical question but this is my biggest doubt. Kindly suggest

解决方案

There are so many answers around there but people always get confused. I know this because I got confused once a while ago. After some time, I grasped the concepts.

  1. Bind object/function manually in order to play with state or props inside the function and to avoid scope-related issues

Not exactly true. You don't need to bind the functions to play with state or props. You bind the function to this when you lose this context in the scope. For example in a callback function.

class App extends React.Component {
  state = {
    name: "foo",
  }
  aFunction() {
    console.log( this.state.name );
  }
  render() {
    return <div>{this.aFunction()}</div>;
  }
}

You don't need to bind your function since this points your class and you don't lose its context. But if you use your function in a callback like a button, you have to bind it:

class App extends React.Component {
  state = {
    name: "foo",
  }
  aFunction() {
    console.log( this.state.name );
  }

  render() {
    return (
      <div>
        <button onClick={this.aFunction}>Click</button>
      </div>
    );
  }
}

This does not work since you lose the context. Now, you need to get its context back somehow right? Ok, let's see how we can do this. First, I want to bind it in the button callback.

<button onClick={this.aFunction.bind(this)}>Click</button>

Yeah, this works. But, it will be recreated in every render. So:

  1. Bind object/function always in constructor but not directly in render

Yes. Do not bind it like I did above, do it in your constructor.

  1. If you do it in constructor then Webpack creates new object/function in bundle.js file only once when your component renders for the first time

  2. If you do it directly in render then Webpack will create a new object/function in bundle.js file every time your component renders and re-render

You are summarizing here what I've tried to explain up to now. But, I suppose Webpack is not the one doing this, your App is.

  1. If you don’t bind then you can’t access state or props. You have to assign current object to a local variable otherwise this.state or this.props is undefined

Again, if you use your function inside your class scope, you don't have to bind it. If you use this function outside of your class, like a button callback, you have to bind it. This is not related to state or props. This is related to using this.

Your second option for binding is doing the binding in the constructor by using a regular function and the third one is using an arrow function without binding.

Now, arrow functions.

1.No need to bind an object/function in constructor nor render

Yes.

  1. You no need to depend on local variable interms of current object i.e., let that = this;

Yes.

  1. You will not have scope issues and object/function binding takes automatically

Yes.

But my query is that I heard that it’s recommended to use normal function and bind it in constructor rather than using arrow function because arrow functions create new object/function in Webpack bundle.js every time your component renders & re-renders.

Like everybody said, that depends on where you use them.

render() {
    return (
        <div>
            <button onClick={() => this.aFunction()}>Click</button>
        </div>
    );
}

Here, it will be recreated in every render. But if you don't need to pass any argument to it, you can use it by reference.

render() {
    return (
        <div>
            <button onClick={this.aFunction}>Click</button>
        </div>
    );
}

This works as the previous one. So, if you see a () in your render method, this function recreated in every render. Regular or an arrow one, doesn't matter. If you are invoking it somehow, then you are recreating it. This applies to bind in the render like aFunction.bind(this). I see () there.

So, use functions by their references to avoid this issue. Now, the big question is what happens when we need some arguments? If you use an arrow function to pass an argument then try to change your logic.

But is it really important as much? Like @Eric Kim said, optimizing is an issue if you really need it. This is a general suggestion since I've heard this from lots of people. But personally, I am trying to avoid using functions if they will be recreated in every render. But again, this is totally personal.

How can you change your logic? You are mapping over an array with an item and creating a button. In this button, you are using a function that passes item's name to a function.

{
    items.map( item =>
        <button onClick={() => this.aFunction(item.name)}>Click</button>
    )
}

This function will be recreated in every render for each item! So, change your logic, create a separate Item component and map it. Pass the item, aFunction as props. Then with a handler function in this component use your function.

const Item = ( props ) => {
    const handleClick = () => props.aFunction( props.item.name );
    return (
        <button onClick={handleClick}>Click</button>
    );
}

Here, you are using an onClick handler with its reference and it invokes your real function. No function will be recreated in every render. But, as a downside, you need to write a separate component and a little bit more code.

You can apply this logic most of the time. Maybe there will be some examples you can't, who knows. So the decision is yours.

By the way, the Medium post that @widged gave in the comments is a famous discussion about this issue. Are arrow functions really slower than the regular ones? Yes. But how much? Not so much I guess. Also, this is true for transpiled code. In the future when they become native, then they will be the faster ones.

As a personal side note. I was using arrow functions all the time since I like them. But a while ago in a discussion, someone said

When I see an arrow function in the class I think that: 'This function is being used/called outside of this class'. If I see a regular one I understand that this function called inside the class.

I really liked this approach and now if I don't need to call my function outside of my class I am using a regular one.

这篇关于React:哪个是推荐的箭头或正常功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆