繁体   English   中英

为什么我的 onClick 在我的 React 项目中不起作用

[英]Why is my onClick not working in my React Project

目前,我正在尝试在业余时间使用 React 做一个关于游轮的网站。 这是我目前正在处理的存储库广告分支的链接https://github.com/RobertWSON/Personal-ship-project/tree/robs-shipslist-under-cruiselines

我目前遇到的问题是,当单击 Cruise Line Heading 时,它应该展开以显示该 Cruise Line 的船舶列表,如果再次单击,它会折叠以仅显示 Cruise Line Heading。 目前我有点困惑,至于我如何才能完成这项工作,而且我还没有让它工作。

到目前为止,我已经设法让 Cruise Lines 在页面的http://localhost:3000/#/cruiselines上显示为标题按钮(不过我希望它跨页面,我相信你可以使用 CSS Flexbox)

CruiselistHeaders组件:

import React from 'react';
import {getCruiseLines } from '../api/api'
import ListofShips from './ListofShips'

class CruiseListHeader extends React.Component {
    constructor(props)  {
        super(props)

        //setting intial state for Cruise Heading and shipsList and initialize cruiseHeaders as an empty array
        this.state = {
            cruiseHeaders: [],
            shipsList: {isOpen: false}
        } 

        //binding methods for Cruise Line Headers and Handle Click Function
        this.setUpCruiseLines = this.setUpCruiseLines.bind(this),
        this.handleClick = this.handleClick.bind(this)
    }  

    componentDidMount() {
        console.log('cdm')
        this.setUpCruiseLines()
    }

    setUpCruiseLines()  {
        console.log('getcruiselines')
        getCruiseLines()
            .then(res   =>  {

                this.setState({
                    cruiseHeaders: res
                })
            })
    }

    /* There will be Headings for all the Cruise Lines.
        When a Cruise Line Heading is clicked, it goes to ListofShips Component and the Ships List opens up for that Heading.
        When user clicks on a Cruise Line Heading, when a Ships List is open, the Ships List Collapses.*/
        // If we click on Cruise Line Heading, then a shipsList is Opened and we go to ListofShips Component, 
        // else if we click on Cruise Line Heading when shipsList is Open then just the Cruise Line Heading is shown. 

    handleClick(event)   {
        //This handleClick sorts out the changing of state, when Cruise Heading is clicked

        //this handleClick function should only handle the 'isOpen' value in the state.
        //any renders supposedly to be made on the 'render' method instead.
        this.setState(prevState =>  ({
            shipsList:  {
                //will reverse prevState of isOpen.
                isOpen: !prevState.shipsList.isOpen,
            }
        }))
    }

    // This renders at the start when the page loads and also when you close a list

    //We can handle the way you render the component that depends on the this.state.shipsList.isOpen this way.  
    render()    {
        //destructive declaration for isOpen from inside shipsList in the state.
        const {shipsList: {isOpen}} = this.state

        return  (

            <React.Fragment>

                {/* Map the Cruiseline Headings for each Cruise Line to display them on the page
                I am currently get all Cruise Lines for each Ship. I only want each Cruise Line appear once and
                I want to map ship because I need each ship displayed in a List for a Cruise Line when isOpen is True. */}
                {this.state.cruiseHeaders.map (ship =>  {

                return  (
                    <div>
                        {
                            //Line below has Conditonal Operator that displays ShipsList when isOpen is True. 
                            //isOpen && <ListofShips />
                            isOpen == true && <ListofShips/>
                        }

                        <h3 key = {ship.cruise_line}><button onClick = {this.handleClick}>{ship.cruise_line}</button></h3>

                    </div>

                    )

                    })
                }  

            </React.Fragment> 
        )
    }
} 

export default CruiseListHeader

ListofShips组件:

import React from 'react'
// import {Link} from 'react-router-dom'
import {getListofShips} from '../api/api'
import { HashLink as Link} from 'react-router-hash-link'


class ListofShips extends React.Component {
    constructor(props){
      super(props)

      this.state = {
        //initialize shipsList as an empty array
        shipsList: []

      }
      this.setUpShips = this.setUpShips.bind(this)
      //this.onHover = this.onHover.bind(this)
    }

    componentDidMount(){
      console.log('cdm')
      this.setUpShips()
    }

    setUpShips() {
      //console.log('getShips')
      console.log('getListofShips')
      //getShips()
      getListofShips()

      .then(res =>  {

        this.setState({
          shipsList: res  
        })
      })
    }

    //This is an onMouseOver event for when you run your mouse over ship in it's list
    // onHover(event)  {

    //   getInitialState

    //   this.setState = {}
    // }

    findShipNames(ship) {

      ship.cruise_line.id = ship.ship_name.id

      return ship.ship_name

      // This function helps display the Cruise Ships based on the Cruise Line

      // Example Code
      //   For Cruise_line === "Carnival"

      //   Ships Displayed =

      //   You have to group the Cruise Lines by their corresponding Ships, somehow

      //   return ship.ship_names

      //   this returns the Ship Names based on there Cruise Lines                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 

    }

  render()  {

    return  (

      <React.Fragment>

      <ol>
        {this.state.shipsList.map (ship => {  

          return   (
              // <li className = "shipsList" key = {ship.cruise_line} onMouseOver={this.onHover}><link smooth to = {`/cruiselines/${ship.cruise_line}#${ship.ship_name}`}>{this.findShipName(ship)}</link></li>
              <li className = "shipsList" key = {ship.cruise_line}><Link smooth to = {`/cruiselines/${ship.cruise_line}#${ship.ship_name}`}>{this.findShipName(ship)}</Link></li>

          )

          // I have to find a key that can display each ship name for each Headings Ships List.
          // The Link will be an Anchor Link to that specific ship, on it's Cruise Line Page.
          // Note: The Cruise Line Page, can have a Review for more than one ship and will be a Review Component.   

            // I would like to do a onMouse Hover function, so that when you run your mouse over ship in list a corresponding image appears

        })
        }
      </ol>

      </React.Fragment>
    )  
  }

}

export default ListofShips

当我单击 Cruise Line 时,ListofShips 组件不工作,我期望的结果是 onClick 以我上面描述的方式工作。

我希望我可以在这里放一个屏幕截图,以便更容易地显示错误,它们在下面

ListofShips.jsx:75 Uncaught TypeError: Cannot read property 'map' of null
at ListofShips.render (ListofShips.jsx:75)
at finishClassComponent (react-dom.development.js:7873)
at updateClassComponent (react-dom.development.js:7850)
at beginWork (react-dom.development.js:8225)
at performUnitOfWork (react-dom.development.js:10224)
at workLoop (react-dom.development.js:10288)
at HTMLUnknownElement.callCallback (react-dom.development.js:542)
at Object.invokeGuardedCallbackDev (react-dom.development.js:581)
at invokeGuardedCallback (react-dom.development.js:438)
at renderRoot (react-dom.development.js:10366)
react-dom.development.js:9747 The above error occurred in the <ListofShips> component:
    in ListofShips (created by CruiseListHeader)
    in div (created by CruiseListHeader)
    in CruiseListHeader (created by CruiseLines)
    in div (created by CruiseLines)
    in div (created by CruiseLines)
    in CruiseLines (created by Route)
    in Route (created by App)
    in div (created by App)
    in Router (created by HashRouter)
    in HashRouter (created by App)
    in App

Consider adding an error boundary to your tree to customize error handling behavior.

logCapturedError @ react-dom.development.js:9747
warning.js:33 Warning: Can only update a mounted or mounting component. This usually means you called setState, replaceState, or forceUpdate on an unmounted component. This is a no-op.

Please check the code for the ListofShips component.
printWarning @ warning.js:33
ListofShips.jsx:75 Uncaught (in promise) TypeError: Cannot read property 'map' of null
    at ListofShips.render (ListofShips.jsx:75)
    at finishClassComponent (react-dom.development.js:7873)
    at updateClassComponent (react-dom.development.js:7850)
    at beginWork (react-dom.development.js:8225)
    at performUnitOfWork (react-dom.development.js:10224)
    at workLoop (react-dom.development.js:10288)
    at HTMLUnknownElement.callCallback (react-dom.development.js:542)
    at Object.invokeGuardedCallbackDev (react-dom.development.js:581)
    at invokeGuardedCallback (react-dom.development.js:438)
    at renderRoot (react-dom.development.js:10366)

在映射值之前,您应该在 2 个组件的渲染函数中添加变量验证部分。

 {this.state.shipsList.length && this.state.shipsList.map (ship => {  
...

并且

{this.state.cruiseHeaders.length && this.state.cruiseHeaders.map (ship =>  {
...

有两种方法可以修复它。

解决方案1:(推荐)

在你去setState之前检查 API 响应的值。

CruiselistHeaders组件:

setUpCruiseLines()  {
  console.log('getcruiselines')
  getCruiseLines()
    .then(res => {

      this.setState({
        cruiseHeaders: Array.isArray(res) ? res : [] // check the API response
      })
    })
}

ListofShips组件:

setUpShips() {
  getListofShips()
    .then(res => {
      this.setState({
        shipsList: Array.isArray(res) ? res : [] // check the API response
      })
    })
}

解决方案2:

您必须在继续之前验证状态变量。

{Array.isArray(this.state.shipsList) && this.state.shipsList.map (ship => {
...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM