nikgraf / belle

Configurable React Components with great UX

Home Page:http://nikgraf.github.io/belle/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

belle + radium bug

luisrudge opened this issue · comments

Not sure where's the problem, so I'm cross posting this in the two repos. Radium repo

When using Radium with Belle, I get this error: Uncaught TypeError: iterable.forEach is not a function

Here's the repro: https://github.com/luisrudge/belle-radium-bug

I debug the issue in radium + belle, and it came out that out 2 components - Select / ComboBox are not working well with radium. These components are structured like:

<Select>
  <Placeholder>Select Country</Placeholder>
  <Option value="USA">USA</Option>
  <Option value="UK">UK</Option>
</Select>

Select code expects to get an array of the nested components in props.children:

screen shot 2015-08-16 at 11 38 39 pm

But with radium this array is converted to object:

screen shot 2015-08-16 at 11 38 58 pm

This is breaking the 2 components :(

This isn't a Radium bug; belle should never manipulate this.props.children directly (e.g. by expecting it to be an array). Only the React.Children helpers should be used: https://facebook.github.io/react/docs/top-level-api.html#react.children.

(I mentioned the same thing in FormidableLabs/radium#317)

This makes sense, we will refactor our code for that. Thanks a lot @ianobermiller.

Thanks folks!

Thanks a lot @luisrudge for bringing this up, we will soon fix it.

Thanks @jpuri Belle is amazing!

@jpuri I did some more investigation

With this code we get back this:

<Select>
  <Placeholder>-- Select a Fruit --</Placeholder>
  {
    map(fruits, (fruit, index) => {
      return (
        <Option value={ fruit.value }
                key={ index }>
          { fruit.content }
        </Option>
      );
    })
  }
</Select>

screen shot 2015-08-25 at 03 00 49

If we run map over them: const children = React.Children.map(properties.children, (child) => child); we get:

screen shot 2015-08-25 at 03 01 33

This is the same thing Radium provides us with. Right now it seems clear to me that we should work with objects like this one. I see two options right now:

  1. modify Select, Combobox, Toggle and run const children = React.Children.map(properties.children, (child) => child); in the constructor of each of these components to make children consistent in their usage. We would need to update the helper functions. The downside here is that we unnecessarily iterate through the whole list.
  2. update/add helper functions to be based on React.Children functions. We could build a filter specifically for React children components or a splice specifically for React children.

@jpuri To me options two seems like more work, but the proper implementation. What's your take?

What are the use cases for filtering/splicing children? I don't even think you need to have children as an array for propTypes checks, as in validateChildrenAreOptionsAndMaximumOnePlaceholder (in Select), since you can just do the check while iterating using React.Children.forEach.

Hey @ianobermiller ,
We still need filtering/ splicing in scenario like when user enters some test in combobox, we need options to be filtered. Though I agree with you validateChildrenAreOptionsAndMaximumOnePlaceholder can be improved.

@nikgraf , I would suggest writing new set of helper methods for filtering and other operations like some, index, first which will use React.Children.forEach underneath.
This may be little more code change, but I agree with you that's how we should so it.

@luisrudge @ianobermiller We fixed the issue and cut a new release. The newest version works well with Radium 😄

Aweeeeeeeeesome! Thanks very much, all of you!