【问题标题】:TypeError: Cannot read property 'choice' of null in Gatsby Link StateTypeError:无法在 Gatsby 链接状态中读取 null 的属性“选择”
【发布时间】:2019-09-01 08:36:50
【问题描述】:

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

代码在重新启动 gatsby 开发之前工作,但显示错误 TypeError: Cannot read property 'choice' of null

这个导航栏是一个组件,所以它总是加载在每个页面上

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>

正如你们所看到的,在子导航链接上我放置了父导航的状态名称,所以当我点击子导航时,有添加活动样式的三元运算符

我没有使用 ActiveClassName 或 PartiallyActive,因为我想要的是当我单击 Convention 中的子菜单时,Convention 样式会改变。

【问题讨论】:

标签: reactjs gatsby


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    我看到你在这里设置了状态:

    <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... 之前,您仍然需要检查窗口。


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

    // 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'}`} />
    )
    

    【讨论】:

    • 感谢您的回答,我尝试在 gatsby-browser 上全局设置属性,然后在我的 navbar.js 组件上传递位置。但现在我得到 TypeError: location is undefined 当我尝试以 location.state.choice 访问道具时
    猜你喜欢
    • 1970-01-01
    • 2021-11-23
    • 2020-01-29
    • 2022-01-05
    • 1970-01-01
    • 2019-10-15
    • 2022-01-12
    • 2021-12-04
    • 2021-12-17
    相关资源
    最近更新 更多