Пишу свое первое приложение на React. У него есть домашняя страница и динамические страницы для произведений искусства. Я использую реагирующий маршрутизатор, и я заметил странное поведение, когда перехожу из Home> Art1> Home> 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.info("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.info("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.info("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
Если вы предоставите дополнительный контекст, мы сможем вам помочь
Добавлен контекст выше. Спасибо, что посмотрели - дайте мне знать, если мне нужно добавить дополнительную информацию.





С помощью коллег мы выяснили, что свойство загрузки в состоянии не было возвращено к true при загрузке данных произведения искусства. Я скорректировал файл App.js, чтобы сбросить это свойство, а затем добавил условие загрузки в элемент прожектора файла PieceDetails.js, потому что его нет внутри <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.info("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
}
Пожалуйста, предоставьте мини-версию вашего кода, если нет, пожалуйста, включите код для вашего компонента
PieceDetail