redux 为什么componentDidMount被调用两次?

gg58donl  于 2023-02-12  发布在  其他
关注(0)|答案(1)|浏览(285)

看看下面的代码片段:

import React from 'react';
import {data} from '../data'
import MovieCard from './MovieCard'
import Navbar from './Navbar'
import { addMovies, setShowFavourites } from '../actions';

class App extends React.Component {

  componentDidMount() {
    const {store} = this.props;
    store.subscribe(() => {
      console.log("UPDATED");
      this.forceUpdate(); 
    });

    store.dispatch(addMovies(data)); 
    console.log("STATE", this.props.store.getState());
  }

  isMovieFavourite= (movie) => {
    const {favourites} = this.props.store.getState();
    const index = favourites.indexOf(movie);
    if(index !== -1) {
      // Found the movie
      return true;
    }
    return false;
  }

  onChangeTab = (val) => {
    this.props.store.dispatch(setShowFavourites(val))
  }

  render() {
    const {list, favourites, showFavourites} = this.props.store.getState();
    console.log("RENDER", this.props.store.getState());
    const displayMovies = showFavourites ? favourites : list;
    return (
      <div className="App">
        <Navbar/>
        <div className='main'>
          <div className='tabs'>
            <div className={`tab ${showFavourites ? '' : 'active-tabs'}`} onClick={() => this.onChangeTab(false)}> Movies </div> 
            <div className={`tab ${showFavourites ? 'active-tabs' : ''}`} onClick={() => this.onChangeTab(true)}> Favourites </div>
          </div>

          <div className='list'>
            {displayMovies.map((movie, index) => {
              return <MovieCard 
                movie={movie}
                key={`movie-${index}`}
                dispatch={this.props.store.dispatch}
                isFavourite={this.isMovieFavourite(movie)}
              />
            })}
          </div>
          {displayMovies.length === 0 
            ? <div className='no-movies'>No Movies to display!</div> 
            : null
          } 
        </div>
      </div>
    );
  }
}

在这个应用程序组件中,我得到了redux商店作为 prop 。现在,根据我的理解,控制台的顺序应该是:

RENDER
UPDATED
STATE
RENDER

但实际的顺序是:

RENDER
RENDER // This render is coming from VM2131 installHook.js:1861 but the value is the same as above
UPDATED
STATE
UPDATED
UPDATED
STATE
RENDER
RENDER // This render is coming from VM2131 installHook.js:1861 but the value is the same as above

我不知道为什么会发生这种情况。理想情况下,componentDidMount应该在初始呈现之后只调用一次。

zphenhs4

zphenhs41#

componentDidMount在您的代码中被调用两次的原因是组件正在重新呈现。componentDidMount方法中的forceUpdate方法导致组件重新呈现,这反过来又导致componentDidMount被再次调用。
事情是这样的:

  1. componentDidMount在首次装入组件时调用,并记录存储的状态。
    1.组件订阅存储,存储的状态通过调用store.dispatch(addMovies(data))进行更新。
    1.组件由forceUpdate调用重新呈现,forceUpdate由存储的状态更改触发。
  2. componentDidMount将再次调用,因为组件已重新呈现。
    1.存储的状态将再次记录,并且已更新两次。
    为了避免这个问题,您应该删除forceUpdate方法,因为在这种情况下不需要它。相反,您可以使用react-redux库中的mapStateToProps方法将组件连接到存储,以便每当存储的状态更改时,组件自动重新呈现。

相关问题