简体   繁体   English

React:变量中的 jsx vs function vs 单独的组件

[英]React: jsx in a variable vs a function vs a separate component

For rendering smaller components/jsx within a bigger component, there are multiple approaches that one can follow.为了在更大的组件中渲染更小的组件/jsx,可以采用多种方法。 For example, consider this:例如,考虑一下:

Method 1:方法一:

function BigComponent(props) {
  const renderSmallComponent1 = () => <div>{props.a}</div>;
  const renderSmallComponent2 = () => <div>{props.b}</div>;

  return (
    <div>
      {renderSmallComponent1()}
      {renderSmallComponent2()}
    </div>
  )
}

Method 2:方法二:

function BigComponent(props) {
  const smallComponent1 = <div>{props.a}</div>;
  const smallComponent2 = <div>{props.b}</div>;

  return (
    <div>
      {smallComponent1}
      {smallComponent2}
    </div>
  )
}

Method 3:方法三:

function SmallComponent1({ a }) {
  return <div>{a}</div>;
}

function SmallComponent2({ b }) {
  return <div>{b}</div>;
}

function BigComponent(props) {
  return (
    <div>
      <SmallComponent1 a={props.a} />
      <SmallComponent2 b={props.b} />
    </div>
  )
}

I am just trying to understand the difference in these 3 in terms of我只是想了解这三个方面的区别

  • dev experience,开发经验,
  • how the framework treats them,框架如何对待它们,
  • are there any performance optimizations,是否有任何性能优化,
  • are there differences in runtime behaviours in all of these?所有这些在运行时行为上是否存在差异?
  • Is either one better to use in certain scenarios?在某些情况下使用哪个更好?

These are the things that I understand:这些是我理解的事情:

  • in Method 3, all SmallComponent are React components which are rendered in another component, so they would have a component lifecycle, while in method 1 and 2, they are simple jsx, which does not have lifecycle, so they would not be mounted / unmounted as React components在方法三中,所有的SmallComponent都是 React 组件,在另一个组件中渲染,所以它们会有一个组件生命周期,而在方法一和方法二中,它们是简单的 jsx,没有生命周期,所以它们不会被挂载/卸载作为 React 组件
  • in Method 2, we would be eagerly evaluating the JSX as it is directly a variable, while in method 1, it would only be evaluated when the function is called in render.在方法 2 中,我们会急切地评估 JSX,因为它直接是一个变量,而在方法 1 中,它只会在渲染中调用 function 时进行评估。 So, in case, we have any conditional rendering, the eager evaluation might just be wasteful.因此,万一我们有任何条件渲染,急切的评估可能只是浪费。

A few other helpful articles:其他一些有用的文章:

UPDATE : it seems observation 1 is incorrect as all 3 of them would still be rendered as react components, and hence would have a component lifecycle.更新:似乎观察 1 是不正确的,因为它们中的所有 3 个仍将呈现为反应组件,因此将具有组件生命周期。 So react would mount/unmount them.所以反应会挂载/卸载它们。

UPDATE 2 : No, observation 1 is correct, method 1 and 2 are both treated as regular jsx as part of the BigComponent and they are not treated as react component which have a lifecycle.更新 2 :不,观察 1 是正确的,方法 1 和 2 都被视为常规 jsx 作为 BigComponent 的一部分,并且它们不被视为具有生命周期的反应组件。

UPDATE 3 : There is another method Method 4:更新 3 :还有另一种方法方法 4:

function BigComponent(props) {
  const SmallComponent1 = () => {
  return <div>{props.a}</div>;
  }
  const SmallComponent2 = () => {
  return <div>{props.b}</div>;
  }

  return (
    <div>
      <SmallComponent1 />
      <SmallComponent2 />
    </div>
  )
}

this is similar to Method 3, but Method 3 vs Method 4 is slightly different in execution, when debugging through dev tools.这与方法 3 类似,但是通过开发工具进行调试时,方法 3 与方法 4 在执行上略有不同。

Method 2:方法二:

function BigComponent(props) {
  const smallComponent1 = <div>{props.a}</div>;
  const smallComponent2 = <div>{props.b}</div>;

  return (
    <div>
      {smallComponent1}
      {smallComponent2}
    </div>
  )
}
  • If you want to a large UI into seperate smaller UI, this method will give you best performance because如果您想将一个大 UI 分成单独的小 UI,此方法将为您提供最佳性能,因为
    • It is still just one big UI component.它仍然只是一个大的 UI 组件。
    • react just have to solve variable references. react 只需要解决变量引用。
    • while re-rendering, BigComponent,smallComponent1 and smallComponent2 are rendered together as single unit.在重新渲染时,BigComponent、smallComponent1 和 smallComponent2 作为一个单元一起渲染。
    • smallComponent1 and smallComponent2 cannot have their own state, life cycles and hooks. smallComponent1 和 smallComponent2 不能有自己的 state、生命周期和钩子。
    • smallComponent1 and 2 needs to be re-initialized everytime Bigcomponent state is changed.每次更改 Bigcomponent state 时,都需要重新初始化smallComponent1 和 2。 So it is good practise to wrap them with useMemo() if the result of those smallComponents are coming from an expensive computation.因此,如果这些 smallComponents 的结果来自昂贵的计算,那么最好用useMemo()包装它们。

Method 3:方法三:

function SmallComponent1({ a }) {
  return <div>{a}</div>;
}

function SmallComponent2({ b }) {
  return <div>{b}</div>;
}

function BigComponent(props) {
  return (
    <div>
      <SmallComponent1 a={props.a} />
      <SmallComponent2 b={props.b} />
    </div>
  )
}
  • React needs to resolve reference as well as execute the function after resolving the reference. React 需要解析引用并在解析引用后执行 function。

  • It is a composition of react's actual child components into a large Component.它是将 React 的实际子组件组合成一个大组件。

  • Child components are allowed to have their own hooks .允许子组件有自己的hooks

  • Child components are not re-initialized but are re-rendered if BigComponent state is changed.如果更改 BigComponent state,子组件不会重新初始化,但会重新呈现。

  • There is chance of SmallComponent1 and SmallComponent2 getting re-rendered multiple times on BigComponents rendering once if small components are updating thier own state based on props change in parents.如果小组件根据父项中的道具更改更新它们自己的 state,则 SmallComponent1 和 SmallComponent2 有可能在 BigComponents 渲染一次时被重新渲染多次。

  • if each SmallComponents are supposed to use multiple props which state of BigComponents, Keeping SmallComponents outside BigComponent does offer good developer experience.如果每个 SmallComponents 都应该使用 state BigComponents 的多个 props,将 SmallComponents 保留在 BigComponent 之外确实提供了良好的开发人员体验。

  • I hope Method 1 and Method 4 can also be understood using these above points.我希望方法1和方法4也可以通过以上几点来理解。

  • Note: childcomponents stored in variable and childcompoents as function becomes tricker if your application logic is using ref or DOM element for maininting focus or anchor point of rendering.注意:如果您的应用程序逻辑使用 ref 或 DOM 元素来维护焦点或渲染锚点,则存储在变量和子组件中的子组件 function 会变得更加棘手。

Have you taken a look at the compiled JS in a React project?你看过 React 项目中编译好的 JS 吗?

JSX tags are essentially transformed in to React.createElement statements. JSX 标签本质上被转换为React.createElement语句。 You can read the docs here .您可以在此处阅读文档 Essentially the syntax is:本质上,语法是:

React.createElement(FunctionOrClassComponent, { props }, ...children)

In all three of your examples this would take place.在您的所有三个示例中,都会发生这种情况。 In all three examples, the smaller components are functional components rather than class components.在所有三个示例中,较小的组件都是功能组件,而不是 class 组件。 That is to say, they don't have the React lifecycle methods of a class component, but they can use equivalent React hooks - should you want to.也就是说,它们没有 class 组件的 React 生命周期方法,但是如果您愿意,它们可以使用等效的 React 钩子。

Edited: Evaluation (instantiation and rendering) depends on your render logic.已编辑:评估(实例化和渲染)取决于您的渲染逻辑。 If you have conditional rendering statements or your functions return null (or less content) based on certain conditions, then obviously you're doing less work.如果您有条件渲染语句或您的函数基于某些条件返回 null(或更少的内容),那么显然您所做的工作更少。 And as you rightly pointed out in the comments below, when you assign a JSX.Element to a variable, that is evaluated inline rather than as a result of a function - so that happens immediately.正如您在下面的评论中正确指出的那样,当您将 JSX.Element 分配给变量时,该变量是内联评估的,而不是作为 function 的结果 - 所以这会立即发生。

To me, all three are valid approaches.对我来说,这三种方法都是有效的。 To address your questions:为了解决您的问题:

  • dev experience,开发经验,
    • for small components with minimal state, functional components as variables or lambdas are convenient to write and easily read/parsed when revisiting code at a later date.对于具有最小 state 的小型组件,作为变量或 lambda 的函数组件便于编写,并且在以后重新访问代码时易于读取/解析。 When a component becomes more complex, you may have to reconsider how it's written and perhaps use Class components.当组件变得更复杂时,您可能不得不重新考虑它的编写方式,并且可能使用 Class 组件。
  • how the framework treats them,框架如何对待它们,
    • to my knowledge the framework treats all three of your examples the same in terms of compilation.据我所知,该框架在编译方面将您的所有三个示例都视为相同。 I'm unsure about rendering optimisation.我不确定渲染优化。
  • are there any performance optimizations,是否有任何性能优化,
    • your examples don't depict anything computationally onerous so performance optimization options are not so obvious您的示例没有描述任何计算繁重的内容,因此性能优化选项并不那么明显
  • are there differences in runtime behaviours in all of these?所有这些中的运行时行为是否存在差异?
    • they are all translated to React elements, monitored for props changes, and re-rendered if parents re-render (if things like React.memo are not employed) -- there may be differences vs class-based elements, but I would guess that the runtime differences between your three examples are minimal它们都被翻译成 React 元素,监视道具的变化,并在父母重新渲染时重新渲染(如果没有使用 React.memo 之类的东西)——与基于类的元素可能存在差异,但我猜想您的三个示例之间的运行时差异很小
  • Is either one better to use in certain scenarios?在某些情况下使用哪一种更好?
    • The differences between all three are more a matter of standards or etiquette than functional outcome.这三者之间的差异更多的是标准或礼仪问题,而不是功能结果。 As a developer, I would be able to read and understand all three, but working in a team - I would want to see a standard approach.作为一名开发人员,我能够阅读和理解这三个方面,但在团队中工作 - 我希望看到一种标准方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM