簡體   English   中英

組件渲染已觸發,但DOM未更新

[英]Component render triggered, but DOM not updated

我的第一個React應用程序遇到了問題。 實際上,我有一個組件層次結構(我正在創建一個多媒體電影畫廊),單擊選項卡(由Movie組件表示)時,這些組件必須顯示單個電影的特定描述(SingleMovieDetails)。 問題在於,僅在第一次單擊時更新DOM,然后即使SingleMovieDetails道具發生更改,DOM仍會鎖定在第一個渲染的電影上。

這是我到目前為止編寫的代碼...

//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

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

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;

如果有人可以幫助我,我將不勝感激。 我已經待了兩天了,但我實在無法應付

您的問題僅與一個文件有關:SingleMovieDetails.js

構造函數中,您正在設置組件狀態以使用props進行初始化(首次發送到組件)

但是在您的render()方法內部,您再次引用了該狀態

<Movie size={'big'} movie={this.state.movie}/>

總而言之,這並不是完全錯誤,但是您需要執行以下兩項操作之一:

  1. 添加一個使用nextPropsReceived更新組件狀態的方法(稱為生命周期方法:將接收道具,如果使用的是最新版本,則應使用:getDerivedStateFromProps)

  2. 首選選項 :影片組件不需要狀態,因此之后只需在render函數(this.props.movi​​e)中使用props,就可以刪除構造函數,因為里面沒有特殊的東西。 :)

編輯:所以,這里要澄清一下:由於只設置了一次狀態(並非在每次生命周期更新中都調用構造函數),所以始終只保存第一個值。 從外部更改道具只會觸發render(),但不會再次啟動構造函數; D

這是因為在SingleMovieDetails組件中,您是在狀態中存儲道具值,而不是在道具更改時更新狀態。 constructor不會再次被調用,因此state始終具有初始值。

您有兩種選擇來解決此問題:

  1. 直接使用props值,而不是以狀態(首選方式)存儲數據。 像這樣:

     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> </> ); } } 
  2. 使用getDerivedStateFromProps ,並在更改道具時更新狀態值。

Movie組件也存在相同的問題,請將此行放入render方法中,否則它將始終顯示相同的圖像:

const imgUrl = `http://image.tmdb.org/t/p/w342/${this.props.movie.poster_path}`

並使用此imgUrl變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM