编写我的第一个React应用程序。它有一个主页和艺术品的动态页面。我正在使用react-router,当我从首页> Art1>主页> Art2导航时,我发现行为异常。
在Art2页面上,页面将使用Art1中的数据进行渲染,然后组件将使用Art2中的正确数据进行重新渲染。
编辑:
App.js:
import "babel-polyfill"
import React, { Component } from "react"
import { BrowserRouter as Router, Route, Switch, Redirect } from "react-router-dom"
import Home from "./pages/home"
import PieceDetail from "./pages/pieceDetail"
class App extends Component {
constructor(props) {
super(props)
this.state = {
piece: {},
locations: [],
themes: [],
types: [],
piecesFilters: {
search: ``,
location: ``,
theme: ``,
type: ``
},
selectedMapPoint: ``,
piecesLoading: true,
pieces: [],
homePageData: {},
spotlightPiece: {},
featuredPieces: [],
homePageLoading: true,
pieceDetails: {},
pieceDetailsLoading: true
}
this.getHomePageData = this.getHomePageData.bind(this)
this.getPieceDetails = this.getPieceDetails.bind(this)
this.updatePiecesFilters = this.updatePiecesFilters.bind(this)
}
getHomePageData() {
const api = `https://publicart.onecolumbiasc.com/w/wp-json/wp/v2`
// Fetch home page data (home page settings - spotlight piece, featured posts and pieces)
fetch(`${api}/pages/86`)
.then(response => response.json())
.then(json => {
this.setState({ homePageData: json })
// Fetch and set state for the spotlight piece details using the id from the above page fetch
fetch(
`${api}/pieces/${json.acf.spotlight_piece.ID}?_embed`
)
.then(response => response.json())
.then(json => this.setState({ spotlightPiece: json }))
// Get the ids for all featured pieces for a future fetch
let featuredPiecesIds = json.acf.featured_pieces.map(piece => piece.feature_piece.ID)
fetch(
`${api}/pieces/?include[]=${featuredPiecesIds[0]}&include[]=${featuredPiecesIds[1]}&include[]=${featuredPiecesIds[2]}&_embed`
)
.then(response => response.json())
.then(json => this.setState({ featuredPieces: json, loading: false }))
.then(json => {
return this.setState({
homePageLoading: false
})
}
)
})
}
getPieceDetails(id) {
fetch(
`https://publicart.onecolumbiasc.com/w/wp-json/wp/v2/pieces/${id}?_embed`
)
.then(response => response.json())
.then(json => this.setState(
{
pieceDetails: json,
pieceDetailsLoading: false
}
))
.catch(ex => console.log("parsing failed", ex))
}
updatePiecesFilters(filters) {
this.setState({
"piecesFilters": {
...filters
}
})
if (this.state.piecesFilters.search !== filters.search) {
this.setState({ "piecesLoading": true })
this.getPiecesData(filters.search)
}
}
componentDidMount() {
// get themes
fetch(
`https://publicart.onecolumbiasc.com/w/wp-json/wp/v2/art_theme`
)
.then(response => response.json())
.then(json => {
return this.setState({ "themes": json })
})
.catch(ex => console.log("parsing failed", ex))
// get types
fetch(
`https://publicart.onecolumbiasc.com/w/wp-json/wp/v2/art_type`
)
.then(response => response.json())
.then(json => {
return this.setState({ "types": json })
})
.catch(ex => console.log("parsing failed", ex))
}
render() {
return (
<Router>
<div>
<Switch>
<Route
exact
path="/"
render={
props =>
<Home {...props}
homePageData={ this.state.homePageData }
spotlightPiece={ this.state.spotlightPiece }
featuredPieces={ this.state.featuredPieces }
loading={ this.state.homePageLoading }
getHomePageData={ this.getHomePageData } />
}
/>
<Route
path="/piece/:pieceid"
render={
props =>
<PieceDetail {...props}
piece={ this.state.pieceDetails }
loading={ this.state.pieceDetailsLoading }
getPieceDetails={ this.getPieceDetails }
update={ this.updatePiecesFilters } />
}
/>
</Switch>
</div>
</Router>
)
}
}
export default App
PieceDetail组件:
/*eslint-disable no-unused-vars*/
import React, { Component, Fragment } from "react"
/*eslint-enable no-unused-vars*/
import "whatwg-fetch"
import styled, { ThemeProvider } from "styled-components"
import theme from "../Theme"
import Container from "../components/Container"
import Details from "../components/pieceDetail/Details"
import Footer from "../components/Footer"
import Gallery from "../components/pieceDetail/Gallery"
import Header from "../components/Header"
import HighlightBanner from "../components/pieceDetail/HighlightBanner"
import InfoSection from "../components/pieceDetail/InfoSection"
import Loader from "../components/Loader"
import Main from "../components/Main"
import Spotlight from "../components/Spotlight"
const VideoContainer = styled.div`
margin: ${theme.margin.stackL};
`
const VideoHeading = styled.h1`
font-size: ${theme.fontSizes.fontSize};
`
const Videos = styled.div``
const Video = styled.video`
margin-top: ${theme.spaces.base};
width: 100%;
`
class pieceDetail extends Component {
componentDidMount() {
const { pieceid } = this.props.match.params
this.props.getPieceDetails(pieceid)
}
render() {
return (
<ThemeProvider theme={{ mode: "main" }}>
<div className="App">
{
this.props.piece.acf ?
<Spotlight
image={ this.props.piece._embedded ?
this.props.piece._embedded["wp:featuredmedia"]["0"]
.media_details.sizes["piece-banner"].source_url
: null
}
overlay={{
heading: this.props.piece
? this.props.piece.title.rendered
: null,
subheading: this.props.piece
? this.props.piece.acf.artist
: null
}}
/>
: null
}
<Header />
<div className="flex-grow">
<Loader loading={ this.props.loading }>
{
this.props.piece.acf ?
<Fragment>
<InfoSection
types={this.props.piece.acf.art_types}
year={this.props.piece.acf.year}
themes={this.props.piece.acf.art_themes}
address={this.props.piece.acf.address.address}
locationName={this.props.piece.acf.location_name}
locationNotes={this.props.piece.acf.location_notes}
buttonUrl={this.props.match.params.pieceid}
update={ this.props.update } />
<HighlightBanner
show={this.props.piece.acf.collaboration_details.length > 0}
text={this.props.piece.acf.collaboration_details} />
<Main>
<Container>
<Details
description={this.props.piece.acf.description}
articles={this.props.piece.acf.articles}
/>
{
this.props.piece.acf.gallery ?
<Gallery
piece={this.props.piece}
gallery={this.props.piece.acf.gallery}
lightboxIsOpen={this.props.lightboxIsOpen}
/>
: null
}
{
this.props.piece.acf.videos ?
<VideoContainer>
<VideoHeading>Videos</VideoHeading>
<Videos>
{
this.props.piece.acf.videos.map(item =>
<Video controls src={item.url} key={item.id}>Sorry, your browser doesn't support embedded videos</Video>
)
}
</Videos>
</VideoContainer>
: null
}
</Container>
</Main>
</Fragment>
: null
}
</Loader>
</div>
<Footer />
</div>
</ThemeProvider>
)
}
}
export default pieceDetail
答案 0 :(得分:0)
在同事的帮助下,我们发现在加载艺术品的数据时,处于状态的loading属性未设置为true
。我调整了App.js文件以重置该属性,然后将条件加载项添加到PieceDetails.js文件的Spotlight元素中,因为它不在<Loader>
内。
代码更新
App.js:
getPieceDetails(id) {
// UPDATE /////////////////////////////////////////////
// set the loading back to true before fetch
this.setState({pieceDetailsLoading: true})
fetch(
`https://publicart.onecolumbiasc.com/w/wp-json/wp/v2/pieces/${id}?_embed`
)
.then(response => response.json())
.then(json => this.setState(
{
pieceDetails: json,
pieceDetailsLoading: false
}
))
.catch(ex => console.log("parsing failed", ex))
}
PieceDetails.js:
render() {
return (
<ThemeProvider theme={{ mode: "main" }}>
<div className="App">
{
// UPDATE /////////////////////////////////////////////
// added a check for loading before showing this part
this.props.piece.acf && !this.props.loading ?
<Spotlight
image={ this.props.piece._embedded ?
this.props.piece._embedded["wp:featuredmedia"]["0"]
.media_details.sizes["piece-banner"].source_url
: null
}
overlay={{
heading: this.props.piece
? this.props.piece.title.rendered
: null,
subheading: this.props.piece
? this.props.piece.acf.artist
: null
}}
/>
: null
}