Atlas7 Atlas7 - 4 months ago 15
React JSX Question

ReactJS - Multiple ways to add/modify propTypes of a stateless functional component?

The Question



How come Approach 2 below works?

High Level



I've recently come across two different ways of defining a stateless functional ReactJS component (both works fine):


  • Approach 1:


    1. const Greet1 = function () {...}

    2. Greet1.propTypes = {...}

    3. export default Greet1


  • Approach 2:


    1. Greet2.propTypes = {...}

    2. export default function Greet2 () {...}




Approach 1 makes sense to me: we start by defining
Greet1
, then add/modify its properties.

Approach 2 is the one I don't get. How is it possible that we are allowed to add/modify a property within
Greet2
before
Greet2
itself is defined?

(Or is it more a JavaScript fundamental basics instead of ReactJS specific?)

Detail Example



Say I have a ReactJS
GreetContainer
that wraps the individual presentational components
Greet1
and
Greet2
.

 GreetContainer



This is
GreetContainer.js
- a (can-be-made-stateful) Container Component that wraps Presentation Components:

import React, { PropTypes } from 'react'
import { Greet1, Greet2 } from 'components'

const GreetContainer = React.createClass({
render () {
return (
<div>
<Greet1 message="This is Greet1"/>
<Greet2 message="This is Greet2"/>
</div>
)
},
})

export default GreetContainer


 Greet1



This is
Greet1.js
- a (stateless) Presentational Component (that I understand):

import React, { PropTypes } from 'react'

const Greet1 = function ({message}) {
return (
<div>
<p>{message}</p>
</div>
)
}

Greet1.propTypes = {
message: PropTypes.string.isRequired
}

export default Greet1


 Greet2



This is
Greet2.js
- a (stateless) Presentational Component (that I don't quite understand - it doesn't make sense to me to specify
Greet2
's properties before
Greet2
itself is defined?):

import React, { PropTypes } from 'react'

Greet2.propTypes = {
message: PropTypes.string.isRequired
}

export default function Greet2 ({message}) {
return (
<div>
<p>{message}</p>
</div>
)
}


Updates - on JavaScript Hoisting



The answer provided below suggests approach 2 works because JavaScript uses Hoisting by default (to hoist declarations to the top of code).

Despite this default behaviour, W3Schools JavaScript - Hoisting says it is good practice to declare variables before using them. So I've created
Greet3
(tested and worked) - which I guess might be a better pattern than
Greet1
and
Greet2
.

import React, { PropTypes } from 'react'

function Greet3 ({message}) {
return (
<div>
<p>{message}</p>
</div>
)
}

Greet3.propTypes = {
message: PropTypes.string.isRequired
}

export default Greet3

Answer

In javascript function declarations are hoisted to the top. So in actuality javascript treats this:

Greet2.propTypes = {...}
export default function Greet2 () {...}

like this:

function Greet2 () {...}
Greet2.propTypes = {...}
export default Greet2;