Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSX for...in loop

Given this object:

lst socials = {
  foo: 'http://foo'
}

I want to loop through it in JSX. This works:

let socialLinks = []
let socialBar
for (let social in socials) {
  socialLinks.push(<li>
                     <a alt={social} href={socials[social]}>{ social }</a>
                   </li>)
}
if (socialLinks) {
  socialBar = <div className='align-bottom text-center'>
                <ul className='list-inline social-list mb24'>
                  {socialLinks}
                </ul>
              </div>
}

But this doesn't (social undefined):

let socialBar
if (socials) {
  socialBar = <div className='align-bottom text-center'>
                <ul className='list-inline social-list mb24'>
                  for(let social in socials)
                  {<li>
                     <a alt={social} href={socials[social]}>{ social }</a> // social is undefined
                   </li>}
                </ul>
              </div>
}

What is the reason social is undefined in the 2nd example? I assume there is a scoping issue with the inner brackets but I have not been successful fixing it.

I can do do a forEach with object keys and do as in this post but that's not much different than my working example.

To be clear - I have it working, I simply wish to be clearer on the scoping problem (or syntax error if so) in my 2nd example.

like image 928
cyberwombat Avatar asked Oct 04 '16 03:10

cyberwombat


1 Answers

JSX is just sugar that gets transpiled to a bunch of function calls of React.createElement, which you can find the docs for here: https://facebook.github.io/react/docs/top-level-api.html#react.createelement

ReactElement createElement(
  string/ReactClass type,
  [object props],
  [children ...]
)

Basically your JSX goes from

<div style="color: white;">
  <div></div>
</div>

to

React.createElement('div', { style: { color: 'white' } }, [
  React.createElement('div', {}, [])
])

For the same reason you can't pass a loop to a parameter in a function, you can't put a loop into JSX. It would end up looking like

React.createElement('div', { style: { color: 'white' } }, [
  React.createElement('div', {}, for (;;) <div></div>)
])

which doesn't make sense at all because you can't pass a for loop as a param. On the other hand, a map call returns an array, which is the correct type for the third parameter of React.createElement.

React is still a virtual dom library at the end of the day, but JSX just makes it more familiar to write. hyperscript is another good example of a vdom library, but where JSX is not standard. Their example on their README is similar to what React would look like without JSX:

var h = require('hyperscript')
h('div#page',
  h('div#header',
    h('h1.classy', 'h', { style: {'background-color': '#22f'} })),
  h('div#menu', { style: {'background-color': '#2f2'} },
    h('ul',
      h('li', 'one'),
      h('li', 'two'),
      h('li', 'three'))),
    h('h2', 'content title',  { style: {'background-color': '#f22'} }),
    h('p',
      "so it's just like a templating engine,\n",
      "but easy to use inline with javascript\n"),
    h('p',
      "the intension is for this to be used to create\n",
      "reusable, interactive html widgets. "))
like image 104
m0meni Avatar answered Oct 18 '22 21:10

m0meni