Rebass: innerRef does not work as expected

Created on 13 Sep 2017  路  7Comments  路  Source: rebassjs/rebass

As rightfully pointed out in https://github.com/jxnblk/rebass/issues/72#issuecomment-315534122, since 1.0.0 we should start using innerRef to get the reference as that's the way it's done in styled-components.

However innerRef doesn't actually work as expected. I suspect this has to do with the fact that in src/create-component.js and src/hoc.js components are wrapped in a way that innerRef doesn't get passed down to the children. Some details about this are explained in here: https://github.com/styled-components/styled-components/issues/927#issuecomment-309140340.

A minimal reproducible test case for this issue can be seen here:

import { Input, Button } from 'rebass'

class InputWrapper extends React.Component {

  constructor(props) {
    super(props)
    this.inputRef = null
  }

  render() {
    return (
      <div>
      <Input innerRef={ c => this.inputRef = c } />
      <Button onClick={() => this.inputRef.focus()}>Focus</Button>
      </div>
    )
  }

}

Most helpful comment

I haven't been able to get innerRef working with 2.0 either yet.
However, using the <Ref /> component from Semantic UI React has solved this (at least temporarily) for me.

import { Ref } from 'semantic-ui-react';
import { Input, Button } from 'rebass';
/* ... */
<Button onClick={() => console.log(this.InputRef.value)}>Log Value</Button>
<Ref innerRef={(node) => { this.InputRef = node }}>
  <Input />
</Ref>

Perhaps a similar helper could be added to Rebass.
https://github.com/Semantic-Org/Semantic-UI-React/tree/5a37f2899fcb048a01a6a51d078455f5eb9219df/src/addons/Ref

All 7 comments

@jxnblk Any ideas on how to get around this?

any updates on this?

nope. Unless you tweak the way the HOC creates the components, there's no other way to fix this

I haven't been able to get innerRef working with 2.0 either yet.
However, using the <Ref /> component from Semantic UI React has solved this (at least temporarily) for me.

import { Ref } from 'semantic-ui-react';
import { Input, Button } from 'rebass';
/* ... */
<Button onClick={() => console.log(this.InputRef.value)}>Log Value</Button>
<Ref innerRef={(node) => { this.InputRef = node }}>
  <Input />
</Ref>

Perhaps a similar helper could be added to Rebass.
https://github.com/Semantic-Org/Semantic-UI-React/tree/5a37f2899fcb048a01a6a51d078455f5eb9219df/src/addons/Ref

I've been digging through the code for Input a bit and followed its execution.

The problem appears to be that here
https://github.com/jxnblk/styled-system/blob/1303da49ebf82f9d5db49ba9a816ceddac58a4a6/system-components/src/System.js#L52
system-components uses clean-tag to insert another component-layer.

The call to createComponent here should create a styled('input'), but it creates a styled(Clean.tag)

One solution would be to make the render function of BaseStyledComponent smarter.

Actually, I see now that there's already a hack in place to make this work when styling a clean-tag component directly...

But in this case, the clean-tag thing is wrapped in another component here

So, what needs to happen is that system-components adds that same hack:

const div = props => React.createElement(tag, props)
div.defaultProps = {
  blacklist: Object.keys(propTypes)
}
// Trick styled-components into passing innerRef
div.styledComponentId = 'lol'

Closing this since I think #188 addresses this. Please open a new issue if not

Was this page helpful?
0 / 5 - 0 ratings

Related issues

ferdinandsalis picture ferdinandsalis  路  5Comments

coreybruyere picture coreybruyere  路  5Comments

luftywiranda13 picture luftywiranda13  路  4Comments

jamesknelson picture jamesknelson  路  4Comments

gi-alec picture gi-alec  路  6Comments