为什么 react-single-page-navigation 只能在没有构造函数和状态的组件中工作?

Why is react-single-page-navigation only working in Components without constructor and state?

我目前正在学习 React,我发现了这个很酷的包:https://www.npmjs.com/package/react-single-page-navigation

我开始使用它,一切顺利。然后我想让我的网络应用程序响应,所以我为小屏幕构建了一个移动导航(简单的下拉菜单)。

首先,这个导航也很管用!下拉列表始终显示,我可以点击按钮及其参考,然后通过平滑滚动导航到所需的部分。 由于下拉菜单的显示和隐藏功能,我向移动导航组件添加了一个带有状态 menuVisible 的构造函数,并添加了两个函数来处理“打开下拉菜单”按钮上的点击以及除下拉项目之外的任何其他地方的点击(标准下拉机制)。

这个机制运作良好,dropdwon 看起来不错。但是:导航不再起作用。相反,我总是在我的网络应用程序的第一部分上下“导航”一些像素。

这是可用的桌面导航组件:

import React, {Component} from 'react';

export default class DesktopNavigation extends Component {
    render() {
        return (
            <nav className={this.props.sticky ? 'navbar navbar--sticky' : 'navbar'} id='mainNav'>
                <div className='navbar--logo-holder'>
                    <img alt='logo' className='navbar--logo'/>
                    <h1 className={this.props.sticky ? 'navbar--logo-text-sticky' : 'navbar--logo-text'}>Booyar</h1>
                </div>
                <ul className='navbar--link'>
                    <div ref={this.props.refs.Home} onClick={() => this.props.goTo('Home')}>
                        <div className={(this.props.activeElement === 'Home' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Home
                        </div>
                    </div>
                    <div ref={this.props.refs.About} onClick={() => this.props.goTo('About')}>
                        <div className={(this.props.activeElement === 'About' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            About
                        </div>
                    </div>
                    <div ref={this.props.refs.Services} onClick={() => this.props.goTo('Services')}>
                        <div className={(this.props.activeElement === 'Services' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Services
                        </div>
                    </div>
                    <div ref={this.props.refs.Projects} onClick={() => this.props.goTo('Projects')}>
                        <div className={(this.props.activeElement === 'Projects' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Projects
                        </div>
                    </div>
                    <div ref={this.props.refs.Contact} onClick={() => this.props.goTo('Contact')}>
                        <div className={(this.props.activeElement === 'Contact' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Contact
                        </div>
                    </div>
                </ul>
            </nav>
        );
    }
}

以下是无法正常工作的移动导航组件:

import React, {Component} from 'react';
import DropdownMenu from "./dropdownMenu";


export default class MobileNavigation extends Component {

    constructor(props) {
        super(props);
        this.state = {
            sticky: this.props.sticky
        }
    }

    callbackIsSticky = (isSticky) => {
        this.setState({sticky: isSticky})
    }

    render() {
        return (
            <nav className={this.state.sticky || this.props.sticky ? "mobile-navbar mobile-navbar-sticky" : "mobile-navbar"} id="mainNav">
                <div className="mobile-navbar--logo-holder">
                    <img alt="logo" className="mobile-navbar--logo"/>
                </div>
                <DropdownMenu
                    refs={this.props.refs}
                    activeElement={this.props.activeElement}
                    goTo={this.props.goTo}
                    sticky={this.props.sticky}
                    callback={this.callbackIsSticky}
                />
            </nav>
        );
    }
}
import React, {Component} from 'react';

/**
 * This class represents the dropdown menu in mobile view.
 */
export default class DropdownMenu extends Component {

    constructor(props) {
        super(props);
        this.state = {
            menuVisible: false
        }
        this.handleClick = this.handleClick.bind(this);
        this.handleOutsideClick = this.handleOutsideClick.bind(this);
    }

    handleClick() {
        if (!this.state.menuVisible) {
            document.addEventListener('click', this.handleOutsideClick, false);
            this.props.callback(true);
        } else {
            document.removeEventListener('click', this.handleOutsideClick, false);
            this.props.callback(false);
        }

        this.setState(stateBefore => ({
            menuVisible: !stateBefore.menuVisible,
        }));
    }

    handleOutsideClick(event) {
        if (this.node.contains(event.target)) {
            return;
        }

        this.handleClick();
    }

    render() {
        const items =
            <div className={'dropdown-items'}>
                <button
                    ref={this.props.refs.Home} onClick={() => this.props.goTo('Home')}
                    className={(this.props.activeElement === 'Home' ? "active-mobile-page " : "")}>
                    Home
                </button>
                <button
                    ref={this.props.refs.About} onClick={() => this.props.goTo('About')}
                    className={(this.props.activeElement === 'About' ? "active-mobile-page " : "")}>
                    About
                </button>
                <button
                    ref={this.props.refs.Services} onClick={() => this.props.goTo('Services')}
                    className={(this.props.activeElement === 'Services' ? "active-mobile-page " : "")}>
                    Services
                </button>
                <button
                    ref={this.props.refs.Projects} onClick={() => this.props.goTo('Projects')}
                    className={(this.props.activeElement === 'Projects' ? "active-mobile-page " : "")}>
                    Projects
                </button>
                <button
                    ref={this.props.refs.Contact} onClick={() => this.props.goTo('Contact')}
                    className={(this.props.activeElement === 'Contact' ? "active-mobile-page " : "")}>
                    Contact
                </button>
            </div>;

        return (
            <div className={'dropdown-menu' + (this.state.menuVisible ? ' dropdown-menu-open' : '')}
                 ref={node => this.node = node}>
                <button className={'hamburger hamburger--elastic' + (this.state.menuVisible ? ' is-active' : '')} onClick={this.handleClick} type={'button'}>
                    <span className="hamburger-box">
                        <span className={'hamburger-inner' + (this.state.menuVisible || this.props.sticky ? ' hamburger-inner-sticky' : '')}>
                        </span>
                    </span>
                </button>
                {this.state.menuVisible ? items : undefined}
            </div>
        );
    }
}

当然,一切都被 <ScrollNavigation elements={{Home: {}, About: {}, Services: {}, Projects: {}, Contact: {}}}>...</ScrollNavigation> 包装起来,如 react-single-page-navigation 的文档所述。

我决定是显示移动导航还是桌面导航 css 以及以下 class:

import React, {Component} from 'react';
import MobileNavigation from "./mobileNavigation";
import DesktopNavigation from "./desktopNavigation";

export default class Navigation extends Component {

    render() {
        return (
            <div>
                <MobileNavigation
                    refs={this.props.refs}
                    activeElement={this.props.activeElement}
                    goTo={this.props.goTo}
                    sticky={this.props.isSticky}/>
                <DesktopNavigation
                    refs={this.props.refs}
                    activeElement={this.props.activeElement}
                    goTo={this.props.goTo}
                    sticky={this.props.isSticky}/>
            </div>
        );
    }
}

我希望这些信息足够了。我不喜欢 post 我的整个项目,但我认为这是没有必要的。桌面导航按预期工作。移动导航仅在主页部分导航毫米。我认为有一个基本的反应“东西”导致了我无法弄清楚的行为,因为当我取消注释除了渲染方法之外的所有东西时移动导航工作(以及调用未注释的东西的渲染方法中的东西;)) .

如果您需要更多信息或有其他问题,请提问! :)

提前致谢,节日快乐!

马克西莫图斯

好的,所以我的错误是将滚动导航 ref={this.props.refs.Home}(等)的引用放到了按钮上。我不知何故误解了 instructions in the docs of react-single-page-navigation。 ref 属性就像 'anchor' 所以滚动导航知道滚动到哪里。我将这个 ref 添加到按钮本身,所以导航只是滚动到按钮的位置。

所以我只是将它从按钮中删除,现在一切正常(桌面导航也一样,我知道为什么它以前在那里工作但出现同样的错误)。

<ul className='navbar--link'>
                    <div onClick={() => this.props.goTo('Home')}>
                        <div
                            className={(this.props.activeElement === 'Home' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Home
                        </div>
                    </div>
                    <div onClick={() => this.props.goTo('About')}>
                        <div
                            className={(this.props.activeElement === 'About' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            About
                        </div>
                    </div>
                    <div onClick={() => this.props.goTo('Services')}>
                        <div
                            className={(this.props.activeElement === 'Services' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Services
                        </div>
                    </div>
                    <div onClick={() => this.props.goTo('Projects')}>
                        <div
                            className={(this.props.activeElement === 'Projects' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Projects
                        </div>
                    </div>
                    <div onClick={() => this.props.goTo('Contact')}>
                        <div
                            className={(this.props.activeElement === 'Contact' ? 'active-page ' : '') + (this.props.sticky ? 'navbar--link-item-sticky' : 'navbar--link-item')}>
                            Contact
                        </div>
                    </div>
                </ul>

现在,滚动导航的触发器只定义了 goTo 属性,而 ref 属性由我网站的部分定义。