javascript - React functional component vs. plain-old JS function that returns React element - Stack Overflow

Suppose I define a simple React functional ponent like this:const Greeter1 = ({name}) => <h1>H

Suppose I define a simple React functional ponent like this:

const Greeter1 = ({name}) => <h1>Hello {name}</h1>;

I can also define an equivalent plain-old JS function that returns a React element, like this:

const Greeter2 = name => <h1>Hello {name}</h1>;

The "React" version is of course also just a normal JS function, taking in a JS object instead of a string. We could use either of these functions within plain JS to get the greeter element for a given name, just with slightly different caller syntax:

const greeterElement1 = Greeter1({ name: "Bob" });
const greeterElement2 = Greeter2("Bob");

Within a React expression though, we can call these functions in a few different ways:

const someReact1 = <div>{ Greeter2("Bob") }</div>;
const someReact2 = <div>{ Greeter1({ name: "Bob" }) }</div>;
const someReact3 = <div><Greeter1 name="Bob" /></div>;

My question: Are there any effective differences between these calling styles other than syntax aesthetics? I assume someReact1 and someReact2 are virtually identical, but I'm not sure about someReact3. Does using the React ponent syntax change the way React treats things? Does it affect behavior or performance in any way? Or is it merely syntactic sugar?

When doing a diff on the virtual DOM tree, does React forgo paring within a functional ponent if its attributes haven't changed between renderings? And if so, am I correct to assume that that optimization would be lost when calling functions directly as in someReact1?

I want to know b/c in some cases I actually prefer the style of someReact1 as it allows me to use functional programming techniques like currying more easily, plus sometimes it's nice to not have to specify parameter names when calling. But am I paying some kind of penalty by doing so? Am I better off sticking with the traditional syntax?

Suppose I define a simple React functional ponent like this:

const Greeter1 = ({name}) => <h1>Hello {name}</h1>;

I can also define an equivalent plain-old JS function that returns a React element, like this:

const Greeter2 = name => <h1>Hello {name}</h1>;

The "React" version is of course also just a normal JS function, taking in a JS object instead of a string. We could use either of these functions within plain JS to get the greeter element for a given name, just with slightly different caller syntax:

const greeterElement1 = Greeter1({ name: "Bob" });
const greeterElement2 = Greeter2("Bob");

Within a React expression though, we can call these functions in a few different ways:

const someReact1 = <div>{ Greeter2("Bob") }</div>;
const someReact2 = <div>{ Greeter1({ name: "Bob" }) }</div>;
const someReact3 = <div><Greeter1 name="Bob" /></div>;

My question: Are there any effective differences between these calling styles other than syntax aesthetics? I assume someReact1 and someReact2 are virtually identical, but I'm not sure about someReact3. Does using the React ponent syntax change the way React treats things? Does it affect behavior or performance in any way? Or is it merely syntactic sugar?

When doing a diff on the virtual DOM tree, does React forgo paring within a functional ponent if its attributes haven't changed between renderings? And if so, am I correct to assume that that optimization would be lost when calling functions directly as in someReact1?

I want to know b/c in some cases I actually prefer the style of someReact1 as it allows me to use functional programming techniques like currying more easily, plus sometimes it's nice to not have to specify parameter names when calling. But am I paying some kind of penalty by doing so? Am I better off sticking with the traditional syntax?

Share Improve this question asked May 31, 2017 at 15:47 funlambdafunlambda 2752 silver badges8 bronze badges 2
  • I'm in the process of thinking more about this myself. So far, I've figured out that <Greeter1 /> basically piles to React.createElement(Greeter1) whereas the function calls embedded in JSX like {Greeter1()} do not really change when piled. That's as far as I've gotten, but that's the real difference, I think. What effect that has on things I haven't yet figured out. They both render identical in the HTML tree. Not sure what they look like in React's virtual DOM. – J.D. Sandifer Commented Jul 18, 2019 at 5:51
  • There can also be unexpected differences in the way that things behave as a result of differences in the virtual DOM. This caused a layout-breaking CSS bug for me today: stackoverflow./questions/67242769/… – PeterT Commented Apr 24, 2021 at 13:55
Add a ment  | 

2 Answers 2

Reset to default 3

Component functions are (a bit?) faster than class ponents since React 16. Not sure if it's true for prior versions.

Calling ponent function as a function is much faster than calling it via JSX/React.createElement. But, in most cases, this should not affect the way we write our code since JSX is pretty readable. To fill this gap we should use @babel/plugin-transform-react-inline-elements.

However, I understand your passion to call them as functions. For the sake of position, I also find it quite useful. This is even more true for plain functions.
But, again, in the future, functional ponents are going to have a state. If it happens, we may regret our passion :)

Plain functions seem to be faster than ponent functions. However, I have not digged this topic yet. For example, I'm unsure if it works OK with react-hot-reload. Or, its pros/cons for performance and possible optimizations.


IMO, no matter the differences and in any case, optimizations are still on us - be it a shouldComponentUpdate, or memoization, or keys. Components which might not need any optimizations should be cheap to re-render, and vice versa (if it is a pure calculation, not DOM operation, obviously).

Feel free to ment or correct, I'll update my post.

I found an explanation, apparently someone asked a similar question in a Github issue on the official React repository. Here's a link to the issue https://github./facebook/react/issues/16796 and an excerpt from the thread, an answer provided by a contributor:

What I want to understand is this: Is it actually necessary to call React.createElement again, since it is already in the return value of the ponent? Is there any effective difference between that and calling the function ponent directly, like this?

As @hamlim mentioned, the effective difference is that simply calling a ponent as a function wouldn't work if the ponent was more plex than a pure function that returned another React element. React needs the element returned from React.createElement to handle those features.

In the HelloMessage example you could technically just call it as a function, which would be equivalent to doing:

ReactDOM.render(
  <div>Hello Taylor</div>,
  document.getElementById("hello-example")
);

This just inlines the result of HelloMessage, which would render the same UI in the browser. Thats effectively what you're doing by calling HelloMessage as a function. Internally this would be different to React since there's no ponent mounted, but practically speaking the behavior is identical in this trivial example.

For the ParentComponent example, the same constraints apply. You could call the ChildComponent ponents as functions if they were just simple ponents without state or effects, and that would be the same result as just inlining their content into ParentComponent. In same cases this might be what you want, but typically not. If someone added state or effects to one of the ChildComponents, or wrapped it in React.memo or React.lazy, this would break. So use this pattern with caution.

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745421054a4626964.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信