[英]Component render triggered, but DOM not updated
I'm having problems with my first React application. 我的第一个React应用程序遇到了问题。 In practice, I have a hierarchy of components (I'm creating a multimedia film gallery) which, upon clicking on a tab (represented by the Movie component) must show the specific description of the single film (SingleMovieDetails).
实际上,我有一个组件层次结构(我正在创建一个多媒体电影画廊),单击选项卡(由Movie组件表示)时,这些组件必须显示单个电影的特定描述(SingleMovieDetails)。 The problem is that the DOM is updated only on the first click, then even if the SingleMovieDetails props change, the DOM remains locked on the first rendered movie.
问题在于,仅在第一次单击时更新DOM,然后即使SingleMovieDetails道具发生更改,DOM仍会锁定在第一个渲染的电影上。
Here's the code i wrote so far... 这是我到目前为止编写的代码...
//Movie component
import React from "react";
import styles from "./Movie.module.scss";
import PropTypes from "prop-types";
class Movie extends React.Component{
constructor(props){
super(props);
this.imgUrl = `http://image.tmdb.org/t/p/w342/${this.props.movie.poster_path}`;
}
render(){
if(!this.props.size)
return <div onClick={this.props.callbackClick(this.props.movie.id)}
name={this.props.movie.id}
className={styles.movieDiv}
style={{backgroundImage: `url(${this.imgUrl})`}}></div>;
return <div onClick={() => this.props.callbackClick(this.props.movie.id)}
name={this.props.movie.id}
className={styles.movieDivBig}
style={{backgroundImage: `url(${this.imgUrl})`}}></div>;
}
}
Movie.propTypes = {
movie: PropTypes.any,
callbackClick: PropTypes.any
};
export default Movie;
SingleMovieDetails.js SingleMovieDetails.js
import React from "react";
import styles from "./SingleMovieDetails.module.scss";
import Movie from "../Movie";
import SingleMovieDescription from "../SingleMovieDescription";
import MovieCast from "../MovieCast";
import SingleMovieRatings from "../SingleMovieRatings";
class SingleMovieDetails extends React.Component{
constructor(props){
super(props);
console.log(props);
this.state = props;
console.log('constructor', this.state.movie)
}
render(){
console.log('SMD', this.state.movie)
return (
<>
<div className={styles.container}>
<div className={styles.flayer}>
<Movie size={'big'} movie={this.state.movie}/>
</div>
<div className={styles.description}>
<SingleMovieDescription movie={this.state.movie}/>
<MovieCast></MovieCast>
</div>
<div className={styles.ratings}>
<SingleMovieRatings />
</div>
</div>
</>
);
}
}
export default SingleMovieDetails;
MovieCarousel.js MovieCarousel.js
import React from "react";
import PropTypes from "prop-types";
import Movie from "../Movie";
import styles from "./MovieCarousel.module.scss";
import SingleMovieDetails from "../SingleMovieDetails";
class MovieCarousel extends React.Component {
constructor(props) {
super(props);
this.state = [];
this.callbackClickMovie = this.callbackClickMovie.bind(this);
}
callbackClickMovie(id) {
const singleMovieApi = `https://api.themoviedb.org/3/movie/${id}?api_key=b6f2e7712e00a84c50b1172d26c72fe9`;
fetch(singleMovieApi)
.then(function(response) {
return response.json();
})
.then(data => {
this.setState({ selected: data });
});
}
render() {
let details = null;
if (this.state.selected) {
details = <SingleMovieDetails movie={this.state.selected} />;
}
let counter = 6;
let movies = this.props.movies.map(el => {
let element = (
<Movie movie={el} callbackClick={this.callbackClickMovie} />
);
counter--;
if (counter >= 0) return element;
return;
});
let content = (
<>
<h2 className={styles.carouselTitle}>{this.props.title}</h2>
{movies}
{details}
</>
);
return content;
}
}
MovieCarousel.propTypes = {
children: PropTypes.any
};
export default MovieCarousel;
I would be really grateful if someone could help me. 如果有人可以帮助我,我将不胜感激。 I have been on it for two days but I can't really deal with it
我已经待了两天了,但我实在无法应付
your Problem is just related to one file: SingleMovieDetails.js 您的问题仅与一个文件有关:SingleMovieDetails.js
Inside the constructor you´re setting the component state to get initialized with the props (send to the component the first time) 在构造函数中,您正在设置组件状态以使用props进行初始化(首次发送到组件)
But inside your render() method you are referencing that state again: 但是在您的render()方法内部,您再次引用了该状态 :
<Movie size={'big'} movie={this.state.movie}/>
All in all thats not completely wrong, but you need to do one of two things: 总而言之,这并不是完全错误,但是您需要执行以下两项操作之一:
Add a method to update your component state with the nextPropsReceived (Lifecycle Method was called: will receive props, if you are using the latest version you should use: getDerivedStateFromProps) 添加一个使用nextPropsReceived更新组件状态的方法(称为生命周期方法:将接收道具,如果使用的是最新版本,则应使用:getDerivedStateFromProps)
preferred option : you dont need a state for the movie component, so just use the props inside the render function (this.props.movie) afterwards you can also delete the constructor, because there is nothing special inside. 首选选项 :影片组件不需要状态,因此之后只需在render函数(this.props.movie)中使用props,就可以删除构造函数,因为里面没有特殊的东西。 :)
:)
edit: So, just to be clear here: Since you´re only setting the state once (the constructor is not called on every lifecycle update) you will always only have the first value saved. 编辑:所以,这里要澄清一下:由于只设置了一次状态(并非在每次生命周期更新中都调用构造函数),所以始终只保存第一个值。 Changing props from outside will just trigger render(), but wont start the constructor again ;D
从外部更改道具只会触发render(),但不会再次启动构造函数; D
This is because in SingleMovieDetails
component, you are storing the props values in state and not updating the state on props change. 这是因为在
SingleMovieDetails
组件中,您是在状态中存储道具值,而不是在道具更改时更新状态。 constructor
will not get called again so state will always have the initial values. constructor
不会再次被调用,因此state始终具有初始值。
You have two options to solve the issue: 您有两种选择来解决此问题:
Directly use the props values instead of storing data in state (preferred way). 直接使用props值,而不是以状态(首选方式)存储数据。 Like this:
像这样:
class SingleMovieDetails extends React.Component { constructor(props) { super(props); } render() { return ( <> <div className={styles.container}> <div className={styles.flayer}> <Movie size={'big'} movie={this.props.movie}/> </div> <div className={styles.description}> <SingleMovieDescription movie={this.props.movie}/> <MovieCast></MovieCast> </div> <div className={styles.ratings}> <SingleMovieRatings /> </div> </div> </> ); } }
Use getDerivedStateFromProps , and update the state value on props change. 使用getDerivedStateFromProps ,并在更改道具时更新状态值。
Same issue with Movie
component also, put this line in the render method, otherwise it will always show same image: Movie
组件也存在相同的问题,请将此行放入render方法中,否则它将始终显示相同的图像:
const imgUrl = `http://image.tmdb.org/t/p/w342/${this.props.movie.poster_path}`
And use this imgUrl variable. 并使用此imgUrl变量。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.