captivationsoftware / react-sticky

<Sticky /> component for awesome React apps
MIT License
2.64k stars 385 forks source link

Uncaught TypeError: Cannot read property 'getBoundingClientRect' of null #188

Closed dnd closed 7 years ago

dnd commented 7 years ago

I can't seem to get react-sticky to work when attempting to use my own component

              <StickyContainer>
                <Sticky>
                  {({style}) => (<SearchResultsBar style={style} onFilterClick={this.props.handleFilterClick} />)}
                </Sticky>
                ...
              </StickyContainer>

When I attempt the above I get Uncaught TypeError: Cannot read property 'getBoundingClientRect' of null at Sticky.js:61.

var contentClientRect = _this.content.getBoundingClientRect();

If I do the above, but don't attempt to pass any of my own props, and just return the component by name it works:

              <StickyContainer>
                <Sticky>
                  {SearchResultsBar}
                </Sticky>
                ...
              </StickyContainer>

I'm assuming I'm missing something simple, but I don't know what it is. The SearchResultsBar is a stateless functional component if that makes a difference. This is using 6.0.1.

dbarbalato commented 7 years ago

Interesting, might be a bug or an unsavory limitation of the current approach -- can you try with your SearchResultBar as a class extending Component/PureComponent instead and report back to see if that makes any difference?

dnd commented 7 years ago

@dbarbalato, I actually just got finished trying that, and it appears to work correctly as a class extending Component.

dbarbalato commented 7 years ago

Ok, well that's good to know. Obviously undesireable. Would you have any objection to submitting a PR with a reasonable attempt to make this work? I don't do much work with functional components so I wouldn't be the right person to implement.

dbarbalato commented 7 years ago

So on second thought, I don't think this will ever be possible -- stateless functions don't support refs by design, which is the core to this implementation. Maybe possible with some some sort of Component/PureComponent wrapper, but I can't say for sure.

Not to discourage someone from making a PR to work around it. But the mystery as to why has been identified

dnd commented 7 years ago

I'm still somewhat new to react, but creating a HOC seems to make it possible.

const sticky = (ComposedComponent) => class extends Component {
  render() {
    return <ComposedComponent {...this.props}/>
  }
}

const StickySearchResultsBar = sticky(SearchResultsBar)

Whether that's a good solution or not, I don't know. It does work though.

yury-dymov commented 7 years ago

How on Earth could this be not documented after a very lucky catch?

lukemarsh commented 7 years ago

@dnd would you be able to share your source code for your fix?

lukemarsh commented 7 years ago

I found a library which does pretty much everything I need if anyone is interested?

Not experiencing the same getBoundingClientRect bug with this one

https://github.com/yahoo/react-stickynode

jtomaszewski commented 5 years ago

It should be documented, yeah.

Another way to fix it is to use React.forwardRef in your pure component function ( https://reactjs.org/docs/forwarding-refs.html ) .

vcarl commented 5 years ago

The repo is open for contributions @jtomaszewski! We'd welcome a PR to the readme if this is still a problem with the latest version.

pupudu commented 5 years ago

If it helps anyone, forwarding the rest of the props to a wrapping div seems to fix the problem

<Sticky>
     {({style, isSticky, ...rest}) => (
         <div {...rest}>
             <SearchResultsBar style={style} onFilterClick={this.props.handleFilterClick} />
         </div>
     )}
</Sticky>