簡體   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