簡體   English   中英

React Redux,我的組件未連接到Redux Store。 我在另一個組件中測試了動作和減速器,它是否對其他組件有效?

[英]React Redux, my component is not connected to Redux Store. I tested the action and reducer in another component, it does work for other components?

流程是這樣的:

  1. 單擊CarouselItem ,這會觸發onClick={this.handleId}

  2. handleId采用ID,該ID是單擊的CarouselItem

  3. this.props.dispatch(fetchRecon(movieId)); 將執行AJAX操作,該操作將返回數據

  4. 並在Redux狀態中,將最初為moviesRecon:[]的屬性設置為moviesRecon:[data] handleId還將使用this.props.history.push(`/movie-detail?query=${movieId}`);將我路由到新頁面this.props.history.push(`/movie-detail?query=${movieId}`);

  5. 我現在應該在組件MovieDetailPage ,該組件當前正在為Carousel組件使用模擬數據。 理想情況下,我應該將this.props.moviesRecon傳遞給Carousel的電影道具。

嘗試這樣做會給我以下錯誤:

TypeError: Cannot read property 'map' of undefined
 const carousel = this.props.movies.map((item, index) => {
| ^  51 |         return (
  52 |             <CarouselItem data={item} index={index} key={this.props.movies[index].id} id={this.props.movies[index].id} />
  53 |         );

以下是我認為相關的組件:CarouselItem.js

import React from 'react';
import './CarouselItem.css';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import { fetchRecon } from '../../actions/index';
import { withRouter } from 'react-router-dom';

export class CarouselItem extends React.Component{

    handleId = e => {
        let movieId = this.props.id
        console.log("carousel item", movieId);
        this.props.dispatch(fetchRecon(movieId));
        this.props.history.push(`/movie-detail?query=${movieId}`);


    }

    render() {

        let genres = this.props.genres;
        let genreList = this.props.genres.length;

        function getGenreText(id) {
            for (let i = 0; i < genreList; i++) {
                if (genres[i].id == id) {
                    return genres[i].name;
                }
            }
        }

        if (this.props.data) {
            return (
                <div className="movieContainer" onClick={this.handleId}>
                    <img className="moviePoster" src={`https://image.tmdb.org/t/p/w500/${this.props.data.poster_path}`} alt={this.props.data.title} />
                    <h3 className="movieName">{this.props.data.title}</h3>
                    <p className="movieGenre">{getGenreText(this.props.data.genre_ids[0])}</p>
                </div>

            );
        }   
    }
}

const mapStateToProps = state => ({
    genres: state.app.genres
});

export default connect(mapStateToProps)(withRouter(CarouselItem));

Carousel.js

import React from 'react';
import CarouselItem from '../CarouselItem/CarouselItem';
import './Carousel.css';
import Slider from "react-slick";
import "slick-carousel/slick/slick.css";
import "slick-carousel/slick/slick-theme.css";

export class Carousel extends React.Component {

  componentDidMount() {
    // the trick
    setTimeout(() => {
      this.forceUpdate();
    }, 50);
  }
    render(){


        console.log("carousel probs", this.props);
        const carousel = this.props.movies.map((item, index) => {
            return (
                <CarouselItem data={item} index={index} key={this.props.movies[index].id} id={this.props.movies[index].id} />
            );
        });

        return (
            <div className="inner-carousel">
            <h2>{this.props.title}</h2>
                <Slider {...settings}>
                    {carousel}
                </Slider>
                <hr className="carousel-divider"/>
            </div>
        )
    }
}



MovieDetailPage.js

import React from 'react';
import { connect } from 'react-redux';
import { Carousel } from '../Carousel/Carousel';
import { withRouter } from 'react-router-dom';
import {fetchRecon} from '../../actions/index';
import { recommended } from './mock';
import { movieDetails } from './mockdetails';
import './MovieDetailPage.css';

export class MovieDetailPage extends React.Component {

    componentDidMount() {
        window.scrollTo(0, 0);

        window.onpopstate = () => {
            const params = (new URL(document.location)).searchParams;
            const clickedMovie = params.get("query");
            console.log('here', clickedMovie);
        }
        const params = (new URL(document.location)).searchParams;
        const movieId = params.get("query");
        console.log('here', movieId);

        // this.props.dispatch(fetchRecon(movieId));
    }


    render() {
        console.log('movie detail', this.props.moviesRecon, this.props)
        return (
            <div className="movieDetail">
                <div className="movieDetail-container">
                    <img className="movieDetail-bg" src={`https://image.tmdb.org/t/p/original/or06FN3Dka5tukK1e9sl16pB3iy.jpg`} />
                </div>
                <div className="main-details">
                    <Carousel title={"Recommended"} movies={recommended} />
                    <Carousel title={"Recommended"} movies={recommended} />
                    <Carousel title={"Recommended"} movies={recommended} />
                    <Carousel title={"Recommended"} movies={recommended} />
                    <Carousel title={"Recommended"} movies={recommended} />
                    <Carousel title={"Recommended"} movies={recommended} />
                    <Carousel title={"Recommended"} movies={this.props.moviesRecon} />
                </div>

            </div>
        );
    }
}

const mapStateToProps = state => ({
    isLoading: state.app.isLoading,
    moviesRecon: state.app.moviesRecon
});

export default connect(mapStateToProps)(withRouter(MovieDetailPage));

對於第29行的MovieDetailPage.js,我在控制台中記錄了以下內容:

movie detail undefined 
{history: {…}, location: {…}, match: {…}, staticContext: undefined}
history: {length: 17, action: "PUSH", location: {…}, createHref: ƒ, push: ƒ, …}
location: {pathname: "/movie-detail", search: "?query=456740", hash: "", state: undefined, key: "dyth5r"}
match: {path: "/movie-detail", url: "/movie-detail", isExact: true, params: {…}}
staticContext: undefined
__proto__: Object

Reducers.js,如有必要,但我已經確認了該操作,並且reducer正確設置了狀態,因為其他組件也可以訪問movieRecon。

const initialState = {
    isLoading: 0,
    genres: [],
    moviesPlaying: [],
    moviesPopular: [],
    moviesUpcoming: [],
    moviesTop: [],
    movieSearch:[],
    moviesRecon: [],
    searchTerm: ""

};

export const Reducer = (state=initialState, action) => {

    if (action.type === FETCH_RECON_SUCCESS) {
        return Object.assign({}, state, {
            moviesRecon: action.recon
        });
    }
}

由於此行,您收到了錯誤消息,

 <Carousel title={"Recommended"} movies={recommended} />

您正在傳遞一個recommended用組件,我可以看到它是在您的情況下使用import { recommended } from './mock';

Carousel組件,您正試圖遍歷movies使用數組map

這就是為什么會出錯的原因,因為recommendedcomponent不是 array

嘗試將array傳遞給所有子組件。

我認為您應該在組件有足夠的時間獲取影片數據之前啟動.map 您可以執行以下操作進行檢查:

Carousel.js

import React from 'react'
import CarouselItem from '../CarouselItem/CarouselItem'
import './Carousel.css'
import Slider from 'react-slick'
import 'slick-carousel/slick/slick.css'
import 'slick-carousel/slick/slick-theme.css'
export class Carousel extends React.Component {
  componentDidMount() {
    // the trick
    setTimeout(() => {
      this.forceUpdate()
    }, 50)
  }

  createCarousels = () => {
    const movies = this.props.movies

    if (movies.length > 0) {
      return movies.map((item, index) => {
        return (
          <CarouselItem
            data={item}
            index={index}
            key={this.props.movies[index].id}
            id={this.props.movies[index].id}
          />
        )
      })
    }
  }
  render() {
    return (
      <div className="inner-carousel">
        <h2>{this.props.title}</h2>
        <Slider {...settings}>{this.createCarousels()}</Slider>
        <hr className="carousel-divider" />
      </div>
    )
  }
}

在旁注中,您似乎正在嘗試將settings對象散布到Slider組件中,但是無論如何您從未定義設置。 應該調查一下。

好的,所以我知道了。 我基本上在更高級別的App.js組件中輸入了導入錯誤,這就是為什么它沒有連接的原因。 我試圖導入名為MovieDetailPage的MovieDetailPage的成員,而不是默認導出,這是我需要的已連接組件。 錯字了...

我有{ MovieDetailPage } ,應該是MovieDetailPage

暫無
暫無

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

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