React Child componentDidMount 没有在 Route 上触发
React Child componentDidMount not triggering on Route
我是 React 的新手,一直在研究使用无头 WP 后端构建我的第一个 React 应用程序。
我无法让 componentDidMount
在我的 MoviePage
class 中触发。我希望有人能帮助我理解我做错了什么。
这是我的代码,它可能并不完美,因为这是我的第一次尝试。
注意代码现在已更改为添加来自评论的建议 - 检查原始代码的编辑历史记录(它仍然损坏)
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
),
document.getElementById('root'));
registerServiceWorker();
App.js
import React from 'react';
import Header from './components/Header';
import Main from './components/Main';
class App extends React.Component {
render() {
return (
<div>
<Header />
<Main />
</div>
)
}
}
export default App;
Header.js
import React from 'react';
import { Link } from "react-router-dom";
class Header extends React.Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
let dataURL = "http://localhost:8888/SBP/website/wp-json/wp/v2/movies?_embed";
fetch(dataURL)
.then(response => response.json())
.then(response => {
this.setState({
movies: response
})
})
}
render() {
let movieLinks = this.state.movies.map((movie, index) => {
return <li key={index}><Link to={'/movies/'+movie.id}>{movie.title.rendered}</Link></li>
});
return (
<header>
<nav>
<ul>
<li><Link to='/movies'>All Movies</Link></li>
{movieLinks}
</ul>
</nav>
</header>
)
}
}
export default Header;
Main.js
import React from 'react';
import { Route } from "react-router-dom";
import Movies from './Movies';
class Main extends React.Component {
render() {
return (
<main>
<Route path='/movies' component={Movies}/>
</main>
)
}
}
export default Main;
Movies.js
import React from 'react';
import { Switch, Route, } from "react-router-dom";
import MoviesHub from './MoviesHub';
import MoviePage from './MoviePage';
class Movies extends React.Component {
render() {
return (
<Switch>
<Route exact path='/movies' component={MoviesHub}/>
<Route path='/movies/:number' component={MoviePage}/>
</Switch>
)
}
}
export default Movies;
MoviesHub.js
import React from 'react';
class MoviesHub extends React.Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
let dataURL = "http://localhost:8888/SBP/website/wp-json/wp/v2/movies?_embed";
fetch(dataURL)
.then(res => res.json())
.then(res => {
this.setState({
movies: res
})
})
}
render() {
let movies = this.state.movies.map((movie, index) => {
return <div key={index}>
<img src={movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url} alt={movie.title.rendered} />
<p><strong>Title:</strong> {movie.title.rendered}</p>
<p><strong>Release Year:</strong> {movie.acf.release_year}</p>
<p><strong>Rating:</strong> {movie.acf.rating}</p>
<div><strong>Description:</strong><div dangerouslySetInnerHTML={ {__html: movie.acf.description} } /></div>
</div>
});
return (
<div>
<h2>Star Wars Movies</h2>
{movies}
</div>
)
}
}
export default MoviesHub;
MoviePage.js
import React from 'react';
class MoviePage extends React.Component {
constructor() {
super();
this.state = {
movie: []
}
}
componentDidMount() {
console.log('MoviePage componentDidMount');
let dataURL = 'http://localhost:8888/SBP/website/wp-json/wp/v2/movies/'+this.props.match.params.number;
fetch(dataURL)
.then(results => {
return results.json();
})
.then(data => {
debugger;
this.setState({
movie: data
})
console.log("movie", this.state.movie);
})
}
render() {
let movie = this.state.movie;
return <div>
<img src={movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url} alt={movie.title.rendered} />
<p><strong>Title:</strong> {movie.title.rendered}</p>
<p><strong>Release Year:</strong> {movie.acf.release_year}</p>
<p><strong>Rating:</strong> {movie.acf.rating}</p>
<div><strong>Description:</strong><div dangerouslySetInnerHTML={ {__html: movie.acf.description} } /></div>
</div>
}
}
export default MoviePage;
作为参考,我正在 this tutorial 构建并试图将其提升到一个新的水平
任何帮助将不胜感激,任何关于如何改进我的代码以符合最佳实践的建议都将非常有用。
谢谢大家
我认为问题在于你实际上并没有将你的 React 应用程序附加到 DOM 任何地方。在某处,您需要使用 ReactDOM 将您的应用附加到页面上的某个根元素。然后,您的组件将挂载并呈现。
你可能看起来像这样:
ReactDOM.render(App, document.getElementById('my-root-element'))
查看 the documentation 了解更多信息。
编辑
我认为您可能在渲染时遇到了导致此问题的错误。如果您在初始渲染时遇到错误,您将永远无法到达 componentDidMount。
如果您查看 MoviePage
class,您在初始化时设置了 movie: []
状态。您最终会获取一部电影,这大概是一个对象。但是在您完成获取数据之前,您将调用渲染函数,它试图访问该电影的数据,例如:
movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url
两个快速提示:
- Pre-fill 你的状态与你期望你的状态 return 的类型相同。因此,如果您希望 movie 成为一个对象,则初始状态为
movie: {}
.
- 在使用数据渲染元素之前,请确保已加载数据。在数据返回之前呈现微调器或加载消息的条件。
示例渲染函数:
render() {
if (Object.keys(movie).length === 0) { // check if movie object is empty
return <div>Data not loaded</div>;
} else {
return (
... whatever you had
);
}
}
我是 React 的新手,一直在研究使用无头 WP 后端构建我的第一个 React 应用程序。
我无法让 componentDidMount
在我的 MoviePage
class 中触发。我希望有人能帮助我理解我做错了什么。
这是我的代码,它可能并不完美,因为这是我的第一次尝试。
注意代码现在已更改为添加来自评论的建议 - 检查原始代码的编辑历史记录(它仍然损坏)
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
),
document.getElementById('root'));
registerServiceWorker();
App.js
import React from 'react';
import Header from './components/Header';
import Main from './components/Main';
class App extends React.Component {
render() {
return (
<div>
<Header />
<Main />
</div>
)
}
}
export default App;
Header.js
import React from 'react';
import { Link } from "react-router-dom";
class Header extends React.Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
let dataURL = "http://localhost:8888/SBP/website/wp-json/wp/v2/movies?_embed";
fetch(dataURL)
.then(response => response.json())
.then(response => {
this.setState({
movies: response
})
})
}
render() {
let movieLinks = this.state.movies.map((movie, index) => {
return <li key={index}><Link to={'/movies/'+movie.id}>{movie.title.rendered}</Link></li>
});
return (
<header>
<nav>
<ul>
<li><Link to='/movies'>All Movies</Link></li>
{movieLinks}
</ul>
</nav>
</header>
)
}
}
export default Header;
Main.js
import React from 'react';
import { Route } from "react-router-dom";
import Movies from './Movies';
class Main extends React.Component {
render() {
return (
<main>
<Route path='/movies' component={Movies}/>
</main>
)
}
}
export default Main;
Movies.js
import React from 'react';
import { Switch, Route, } from "react-router-dom";
import MoviesHub from './MoviesHub';
import MoviePage from './MoviePage';
class Movies extends React.Component {
render() {
return (
<Switch>
<Route exact path='/movies' component={MoviesHub}/>
<Route path='/movies/:number' component={MoviePage}/>
</Switch>
)
}
}
export default Movies;
MoviesHub.js
import React from 'react';
class MoviesHub extends React.Component {
constructor() {
super();
this.state = {
movies: []
}
}
componentDidMount() {
let dataURL = "http://localhost:8888/SBP/website/wp-json/wp/v2/movies?_embed";
fetch(dataURL)
.then(res => res.json())
.then(res => {
this.setState({
movies: res
})
})
}
render() {
let movies = this.state.movies.map((movie, index) => {
return <div key={index}>
<img src={movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url} alt={movie.title.rendered} />
<p><strong>Title:</strong> {movie.title.rendered}</p>
<p><strong>Release Year:</strong> {movie.acf.release_year}</p>
<p><strong>Rating:</strong> {movie.acf.rating}</p>
<div><strong>Description:</strong><div dangerouslySetInnerHTML={ {__html: movie.acf.description} } /></div>
</div>
});
return (
<div>
<h2>Star Wars Movies</h2>
{movies}
</div>
)
}
}
export default MoviesHub;
MoviePage.js
import React from 'react';
class MoviePage extends React.Component {
constructor() {
super();
this.state = {
movie: []
}
}
componentDidMount() {
console.log('MoviePage componentDidMount');
let dataURL = 'http://localhost:8888/SBP/website/wp-json/wp/v2/movies/'+this.props.match.params.number;
fetch(dataURL)
.then(results => {
return results.json();
})
.then(data => {
debugger;
this.setState({
movie: data
})
console.log("movie", this.state.movie);
})
}
render() {
let movie = this.state.movie;
return <div>
<img src={movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url} alt={movie.title.rendered} />
<p><strong>Title:</strong> {movie.title.rendered}</p>
<p><strong>Release Year:</strong> {movie.acf.release_year}</p>
<p><strong>Rating:</strong> {movie.acf.rating}</p>
<div><strong>Description:</strong><div dangerouslySetInnerHTML={ {__html: movie.acf.description} } /></div>
</div>
}
}
export default MoviePage;
作为参考,我正在 this tutorial 构建并试图将其提升到一个新的水平
任何帮助将不胜感激,任何关于如何改进我的代码以符合最佳实践的建议都将非常有用。
谢谢大家
我认为问题在于你实际上并没有将你的 React 应用程序附加到 DOM 任何地方。在某处,您需要使用 ReactDOM 将您的应用附加到页面上的某个根元素。然后,您的组件将挂载并呈现。
你可能看起来像这样:
ReactDOM.render(App, document.getElementById('my-root-element'))
查看 the documentation 了解更多信息。
编辑
我认为您可能在渲染时遇到了导致此问题的错误。如果您在初始渲染时遇到错误,您将永远无法到达 componentDidMount。
如果您查看 MoviePage
class,您在初始化时设置了 movie: []
状态。您最终会获取一部电影,这大概是一个对象。但是在您完成获取数据之前,您将调用渲染函数,它试图访问该电影的数据,例如:
movie._embedded['wp:featuredmedia'][0].media_details.sizes.large.source_url
两个快速提示:
- Pre-fill 你的状态与你期望你的状态 return 的类型相同。因此,如果您希望 movie 成为一个对象,则初始状态为
movie: {}
. - 在使用数据渲染元素之前,请确保已加载数据。在数据返回之前呈现微调器或加载消息的条件。
示例渲染函数:
render() {
if (Object.keys(movie).length === 0) { // check if movie object is empty
return <div>Data not loaded</div>;
} else {
return (
... whatever you had
);
}
}