TypeError:在Gatsby链接状态中无法读取null的属性“选择”

时间:2019-04-10 19:37:03

标签: reactjs gatsby

我试图从下拉导航栏中单击子菜单时添加一些ClassName 这就是导航栏的样子 https://imgur.com/9iCDj7k

该代码在启动gatsby开发之前有效,但是在重新启动gatsby开发之后却显示错误TypeError:无法读取null的'choice'属性

此导航栏是一个组件,因此始终在每个页面上加载

import React from "react"
import { Link } from "gatsby"

const Navbar = () => {
    return (
        <div
            className="collapse navbar-collapse" id="navbarSupportedContent">
            <ul className="navbar-nav mr-auto justify-content-around w-100">
                <li className="nav-item"><Link className="nav-link pb-md-3" activeClassName="nav-link-active" to="/">Home</Link></li>
                <li className="nav-item">

                    <div className={window.history.state.choice === 'Convention' ? 'dropdown nav-link pb-md-3 active' : 'dropdown nav-link pb-md-3'}>
                        <div className="dropdown-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Convention</div>
                        <div className="dropdown-menu" aria-labelledby="dropdownMenuButton"><Link className="dropdown-item" activeClassName="nav-sub-active" to="/convention/general-information" state={{ choice: 'Convention' }}>General Information</Link><Link className="dropdown-item" href="/coming-soon">Plenary & Special Sessions</Link><Link className="dropdown-item" href="/coming-soon">Technology Session</Link>
                            <div
                                className="dropdown-toggle dropdown-item nested-dropitem" id="dropdownMenu1Button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Technical Program</div>
                                <div className="dropright">
                                    <div className="dropdown-menu" aria-labelledby="dropdownMenuButton1"><Link className="dropdown-item" href="/coming-soon">Oral Presentation</Link><Link className="dropdown-item" href="/coming-soon">Poster Presentation</Link></div>
                                </div><Link className="dropdown-item" href="/coming-soon">Download Full Paper</Link><Link className="dropdown-item" href="/coming-soon">Registration</Link></div>
                    </div>
                </li>
                <li className="nav-item">
                    <div className={window.history.state.choice === 'Exhibition' ? 'dropdown nav-link pb-md-3 active' : 'dropdown nav-link pb-md-3'}>
                        <div className="dropdown-toggle" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Exhibition</div>
                        <div className="dropdown-menu" aria-labelledby="dropdownMenuButton"><Link className="dropdown-item" to="/exhibition/why-exhibit" state={{ choice: 'Exhibition' }}>Why Exhibit?</Link><Link className="dropdown-item" to="/exhibition/book-your-space" state={{ choice: 'Exhibition' }}>Book Your Space</Link><Link className="dropdown-item" href="/coming-soon">Exhibitor Services</Link>
                            <Link
                                className="dropdown-item" to="/exhibition/about-the-venue" state={{ choice: 'Exhibition' }}>About the Venue</Link>
                        </div>
                    </div>
                </li>

就像你们看到的那样,在Subnav链接上,我放置了父导航的状态名称,因此,当我单击sub nav时,有三元运算符添加了活动样式

我不使用ActiveClassName或PartiallyActive,因为我想要的是当我单击Convention的子菜单时,Convention样式被更改了。

2 个答案:

答案 0 :(得分:1)

根据文档: gatsby-link,您应该可以使用location来检索状态,但不幸的是,这对我也不起作用,并且会收到与您类似的错误。

我能够使用Link从盖茨比window.history.state检索状态 我在这里找到了答案:gatsby-issue#9091

答案 1 :(得分:0)

我看到您在这里设置状态

<Link
  className="dropdown-item" 
  to="/exhibition/about-the-venue" 
  state={{ choice: 'Exhibition' }}>
  About the Venue
</Link>

但是window.history.state仅在用户已经单击链接时填充。因此,在第一次加载时,它不会存在。另外,在gatsby build期间您可能会遇到问题,因为window对象在那里不可用。

您可以添加一个空检查:

const getHistoryState = (prop) => {
  if (typeof window === 'undefined') return
  if (!window.history.state) return
  return window.history.state[prop]
}

<div className={`dropdown nav-link pb-md-3 ${getHistoryState(choice) === 'Exhibition' && 'active'}`}>

或全局设置该属性:

// gatsby-browser.js

export const onClientEntry = () => {
  window.history.pushState({ choice: '...' }, '')
}

不过,在组件中使用window.history...之前,您仍然需要检查窗口。


为避免完全检查窗口,请使用location传递给页面组件的reach-router对象,例如:

// src/index.js

export default const IndexPage = ({ location }) => (
  <NavBar location={location} />
)

// NavBar.js

const NavBar = ({ location }) => (
  <div className={`class name here ${location.state && location.state.choice && 'active'}`} />
)