React / General

How do you write your functional components?

How do you write your functional components?

React/General · May 14, 2018 at 9:08am

How do you write your functional components?

React / General · May 14, 2018 at 9:08am (Edited 7 months ago)
Hey guys!
A quick question regarding functional components. I keep seeing two common patterns when it comes to creating a functional component:
function Card({ placeholder, definition }) { return ( <StyledCard w={1} mb={2}> <StyledInput placeholder={placeholder} value={definition} type="text" /> </StyledCard> ); } export default Card;
const Card = props => { return ( <StyledCard w={1} mb={2}> <StyledInput placeholder={props.placeholder} value={props.definition} type="text" /> </StyledCard> ); }; export default Card;
Code style aside, what are the nuances of both patterns? How do you prefer to write your functional components?
Thanks for your input!

May 14, 2018 at 9:17am

2nd version + destructure pros + `no return`, like:

const Card = ({ placeholder, definition }) => (
<StyledCard w={1} mb={2}>
<StyledInput
placeholder={placeholder}
value={definition}
type="text"
/>
</StyledCard>
);

export default Card;
like-fill
20
  • reply
  • like

Arrow functions can tempt you to export them directly

export default props => <h1>Hello World</h1>;

which is slightly bad for debugging as it isn't named anymore. Also, if you wish to add `propTypes` to it, it becomes bit verbose as you need to convert it into a named arrow function.

So unless you're doing this, either of the options are fine. I personally like to just use `class extends PureComponent` as my default.

like-fill
4
  • reply
  • like

Neat, thanks guys :)

  • reply
  • like

I use Flow, so typing in pure functions is no problem, but I agree that it's better to not directly export default, because you loose the names. I usually prefer destructuring in the header, because it's immediately clear what the function will be receiving, the only time I don't do that is if I need access to the whole props to pass along to a sub-component `{...props}`.

like-fill
1
  • reply
  • like

(PS: My first puerile response when I read your question title was: "With my keyboard" :))

  • reply
  • like

2nd version + destructure pros + `no return`, like:

const Card = ({ placeholder, definition }) => (
<StyledCard w={1} mb={2}>
<StyledInput
placeholder={placeholder}
value={definition}
type="text"
/>
</StyledCard>
);

export default Card;

The return isnt required since its an arrow function, correct?

  • reply
  • like

Yeah I was just going to say. Eslint always complains when I do that. One neat thing I learnt recently is that you can do

const card = ({title, content}) => 
  console.log(title) || <h1>{title}</h1><p>{content}</p>

if I need a quick console log of something, without having to turn it back into a { return()} structure.

like-fill
8
  • reply
  • like

@houshuang haha! Yeah I'd like to dig into Flow once I get better with React and Redux. Im afraid Flow will throw me over the edge.

  • reply
  • like

One thing that has sometimes caused bugs is when I forgot the {} though. So I do

  • reply
  • like

Right, arrow fns return by default if you ommit curly braces https://jsfiddle.net/fwhg778m/

  • reply
  • like
const Card = (title) => <h1>{title}</h1>

and React says "Expected component or string or null"

  • reply
  • like

To me it would have made so much sense to have implicit return within curly brackets as well, like a lot of other languages, but that's JS :)

  • reply
  • like

@jonlprd With neovim it immediately highlights when I make a Flow mistake, and it's awesome for productivity. Some things are hard to type, and I don't aim for 100% at all, but especially for typing between files and modules, to remember that a certain utility function takes a number and a string, not the other way around, or it requires an object with these keys... Then later when you change the utility function, it immediately tells you all the places you need to update etc.

like-fill
1
  • reply
  • like

We have a monorepo with a main app and lot's of plugins, and we use this shared file to coordinate types between all the different packages. https://github.com/chili-epfl/FROG/blob/develop/frog-utils/src/types.js

  • reply
  • like

I use Flow, so typing in pure functions is no problem, but I agree that it's better to not directly export default, because you loose the names. I usually prefer destructuring in the header, because it's immediately clear what the function will be receiving, the only time I don't do that is if I need access to the whole props to pass along to a sub-component `{...props}`.

Do you have a snippet of this anywhere? I just curious what it looks like syntactically.

  • reply
  • like

@houshuang Good to know! I'm Neovim user as well, so that's great.

  • reply
  • like

Do you have a snippet of this anywhere? I just curious what it looks like syntactically.

Not sure exactly what you are referring to?

  • reply
  • like

@houshuang Just how a functional component would look like with Flow, as you described.

  • reply
  • like

https://youtu.be/Df7fC-SdT7I - I import Flow definitions from that file I linked above (in a different NPM package). Then I show that the exported interface from this plugin has to have the right fields, they have to be at the right type etc. Note that this is all synchronous - I never save the file while I'm editing.

  • reply
  • like

@houshuang Excellent, thank you very much!

  • reply
  • like

Honestly I am thinking more and more to not write any funtional component anymore. They are very unperformant unable to be optimized i have to refactor code if i never need state or lifecycle etc et. However if had to write one i prefer named function amd destructure the props in the top. const { foo, bar } = props and use a return. That helps the most if i need to refactor inyp class

  • reply
  • like

Honestly I am thinking more and more to not write any funtional component anymore. They are very unperformant unable to be optimized i have to refactor code if i never need state or lifecycle etc et. However if had to write one i prefer named function amd destructure the props in the top. const { foo, bar } = props and use a return. That helps the most if i need to refactor inyp class

  • reply
  • like

Never heard that they are unperformant, and I think in the future React will optimize specifically for them.

  • reply
  • like

Well they are. Just try yourself the function component rewrites all its content on the dom instead of diffing properly. But to me the real deal breaker is the cognitive effort of converting to class again (whichbis often)

  • reply
  • like

And you get the additionaal benefit of one less choise TM..

  • reply
  • like
Your message here...

*bold*_italic_`code````codeblock```