我的反应代码正在工作,但刷新页面时出现TypeError:无法读取未定义的属性'Location'

问题描述 投票:0回答:1

[从GamePage开始,它提供了2条路线,分别呈现了GameList和GameDetailPage组件。两者一开始都可以正常工作,但是当我刷新Gamelist组件的页面时,它仍会重新渲染该页面,但是当我刷新GameDetailPage的页面时,会出现错误TypeError:无法读取未定义的属性“ Location”。我不明白为什么每次刷新时都无法从状态获取数据。

gamepage.jsx

import React from "react";
import GamesList from "../../components/games-list/game-list.component";
import { Route } from "react-router-dom";
import GameDetailPage from "../gamedetailpage/gamedetailpage.component";
import {firestore,convertCollectionsSnapshotToMap} from '../../firebase/firebase.utils'
import {connect} from 'react-redux'
import {updateFootballGames} from '../../redux/games/games.actions'

class GamePage extends React.Component {

  unsubscribeFromSnapshot=null;

  //whenever the component mounts the state will be updated with the football games.
  componentDidMount(){
    const {updateFootballGames}=this.props
    const gameRef=firestore.collection('footballgames')
    gameRef.onSnapshot(async snapshot=>{
      const collectionsMap=convertCollectionsSnapshotToMap(snapshot)
      updateFootballGames(collectionsMap)
    })
  }
  render() {
    const { match } = this.props;
    return (
      <div className="game-page">
        <h1>games page</h1>
        <Route exact path={`${match.path}`} component={GamesList} />
        <Route path={`${match.path}/:linkUrl`} component={GameDetailPage}
         />
      </div>
    );
  }
}

const mapStateToProps=state=>({
  games:state.games.games
})

const mapDispatchToProps=dispatch=>({
  updateFootballGames:collectionsMap=>
  dispatch(updateFootballGames(collectionsMap))
})

export default connect(mapStateToProps, mapDispatchToProps)(GamePage);

gamedetailpage.component.jsx

  import React from "react";
    import { connect } from "react-redux";
    import GamePreview from '../../components/game-preview/game-preview.component'
    import GameDetails from '../../components/game-details/game-details.component'

const GameDetailPage = (props) => {
    const {games, match} = props
    const urlparam =match.params.linkUrl
    // const games_array = Object.entries(games)
    const gameObj=games[urlparam]
    console.log('prop',gameObj)


    return (
      <div className="game-list"> 
          <GameDetails game = {gameObj}/>
      </div>

    );

};




const mapStateToProps = (state) => ({
  games: state.games.games,
});

export default connect(mapStateToProps)(GameDetailPage);

game_details.component.jsx

import React from 'react';


const GameDetails = (props) => {
    console.log(props.game.Location)

    return(
    <div>
    Location:{props.game.Location}
    <br/>
    Price:{props.game.Price}
    </div>

    )
}

export default GameDetails;

gamelist.component.jsx

import React from "react";
import './game-list.styles.scss'
import GamePreview from "../game-preview/game-preview.component";
import {connect} from 'react-redux'

const GameList=(props)=>{
    const {games}=props
    console.log(games)
    const game_list=Object.entries(games)
    console.log(game_list)
    return (
      <div className="game-list">
        {game_list.map(game => 
                <GamePreview game = {game[1]}/>)}
      </div>

    );
  }

const mapStateToProps=state=>({
  games:state.games.games
})

export default connect(mapStateToProps)(GameList);

gamepreview.component.jsx

import React from "react";
import "./game-preview.styles.scss";
import { withRouter, Route } from "react-router-dom";


import GamePreviewDetail from "../game-preview-detail/game-preview-detail.component";

const GamePreview = (props) => {
  const { Location, Time, linkUrl, Price } = props.game;
  const { history, match } = props;
  return (
    <div
      className="game-preview"
      onClick={() => history.push(`${match.url}/${linkUrl}`)}
    >
      <div className="game-preview-image">
        <p>Picture goes here</p>
      </div>
      {/* <GamePreviewDetail name = {Location} price={Price}/> */}
      <p>Location:{Location}</p>
      <p>Price:{Price}</p>
    </div>
  );
};

export default withRouter(GamePreview);

app.js

import React from 'react';
import './App.css';
//import dependencies
import { Route, Switch } from "react-router-dom";
//import pages
import HomePage from './pages/homepage/homepage'
import GamesPage from './pages/gamespage/gamespage'
import SignInSignUp from './pages/signin-signup-page/signin-signup-page'

import GameDetailPage from "./pages/gamedetailpage/gamedetailpage.component";

import Header from './components/header/header.component';

import { auth, createUserProfileDocument } from './firebase/firebase.utils';

class App extends React.Component{
  constructor() {
    super();

    this.state = {
      currentUser: null
    } 
  }

  unsubscribeFromAuth = null

  componentDidMount() {
  this.unsubscribeFromAuth = auth.onAuthStateChanged(async userAuth => {
    if (userAuth) {
      const userRef = await createUserProfileDocument(userAuth);
      // check if the snapshot has changed (subscribe)
      // get the user that we just created or that already exists in the db
      userRef.onSnapshot(snapshot => {
        this.setState({
          currentUser: {
            id: snapshot.id,
            ...snapshot.data()}
        })
      })  
    } else {
      this.setState({currentUser: userAuth})
    }

    })
  }

  componentWillUnmount() {
    this.unsubscribeFromAuth();
  }

  render(){
    return(
      <div>
        <Header currentUser = {this.state.currentUser}/>
         <Switch>
          <Route exact path="/" component={HomePage} />  
          <Route path="/games" component={GamesPage} />  
          <Route exact path="/signin" component={SignInSignUp} />  
        </Switch>
      </div>
    )
  }
}
export default App;
reactjs react-redux
1个回答
0
投票

我会尝试使用useParams挂钩。然后使用useParams钩子捕获linkUrl的任何更改。还将useEffectuseEffect一起引入。

gameObj返回URL参数的键/值对的对象。用它来访问当前useStateuseParams

如果您熟悉React类的生命周期方法,可以将match.params Hook视为componentDidMount,componentDidUpdate和componentWillUnmount的组合。

尝试如下修改<Route>组件:

useEffect

+ 1-<GameDetailPage />检查:

[另外,您还可以在const GameDetailPage = (props) => { const { games } = props; let { linkUrl } = useParams(); const [ gameObj, setGameObj ] = useState(null); useEffect(() => { const newGameObj = games[linkUrl]; console.log('game object', newGameObj); setGameObj(newGameObj); }, [games, linkUrl]); return <div className="game-list"> { gameObj && <GameDetails game={ gameObj } /> } </div> } 的返回语句中看到null检查,这仅在您在null数组中找到一个具有gameObj值的值时才帮助呈现这种情况。

我希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.