Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

React .createClass() scroll to ref: scrollIntoView not a function

I'm having trouble figuring out what's wrong when I'm trying to scroll to a "ref". I've been searching like mad and found urls which make complete sense, but it won't work in my scenario.

  • https://github.com/yannickcr/eslint-plugin-react/issues/678
  • http://codepen.io/takatama/pen/mVvbqx

I have an app using react 15.4.2 along with react-router 3.0.0. I have a route to a component that takes an optional route parameter and am trying to use that to scroll to the element on componentDidUpdate(). I've tried implementing a couple different ways but in following the most recent implementation of ref.scrollIntoView() I get an error...

scrollIntoView is not a function

I made sure that the "ref callbacks" exist at the time of componentDidUpdate().

Am I just missing something like using .createClass() is missing methods you get when using a class definition or am I approaching this entirely wrong?

I could just jump to using a package, but things like this in not being able to understand what's going on when being as native as I can bother me.

Code has been simplified to showcase the issue while maintaining a similar flow. There may be discrepancies in code syntax.

APP

const App = React.createClass({
    render() {
        return (
            <Router history={ appHistory }>
                <Route path='home' component={ Home }>
                    <IndexRoute component={ Page } />
                    <Route path='page(/:itemIndex)' component={ Page } />
                </Route>
                <Route path='add-new-item' component={ AddNewItem } />
            </Router>
        )
    }
});

HOME is just a wrapper with a nav bar that renders children based on an active index

ADD NEW ITEM is a component which will goto /page/[index of newly created item]

PAGE

const Page = React.createClass({
    getInitialState() {
        return {
            data: undefined,
            scrollTo: parseInt(this.props.params.goalIndex) || undefined
        };
    },

    componentWillMount() {
        // this gets data and does a setState for data
    },

    componentDidUpdate() {
        let { scrollTo } = this.state;

        if( scrollTo && this['item-' + scrollTo] ) {
            this['item-' + scrollTo].scrollIntoView();
        }
    },

    renderTiles() {
        return this.state.data.map( ( item, index ) => {
            return (
                <Item
                    key={ 'item-' + index }
                    ref={ node => this['item-' + index] = node }
                >
                    <p>foo bar...</p>
                </Item>
            )
        });
    },

    render() {
        return (
            <div>
                { this.state.data && this.renderTiles() }
            </div>
        );
    }
});
like image 876
Jeff Avatar asked Feb 24 '17 20:02

Jeff


1 Answers

A nested React component with a ref is just that and not a DOM element with DOM element methods so Element methods will not be available.

To easily fix, you can wrap the React component in a standard DOM element and assign a ref to that.

renderTiles() {
    return this.state.data.map( ( item, index ) => {
        return (
            <div
                key={ 'item-' + index }
                ref={ node => this['item-' + index] = node }
            >
                <Item>
                    <p>foo bar...</p>
                </Item>
            </div>
        )
    });
},
like image 134
Jeff Avatar answered Oct 12 '22 23:10

Jeff