Как заставить компонент отображать различное содержимое в зависимости от того, по какой ссылке пользователь щелкнул в отдельном компоненте? - PullRequest
0 голосов
/ 31 мая 2018

У меня есть компонент, который отображает список жанров фильмов, сгенерированных из Movies API.Я хочу, чтобы, когда пользователь нажимал на определенный жанр, он отображал фильмы этого указанного жанра.

Моя проблема в том, что единственный способ, которым я могу думать об этом, состоит в буквальном создании разных компонентов для каждого из них.жанр, создайте отдельного создателя действий для каждого жанра в моем Redux, который выполняет GET-запрос к API для каждого жанра, и установите ссылку на этот компонент для указанного жанра.Это кажется действительно трудоемким и неэффективным.

Есть ли способ заставить компонент ShowGenres отображать разные фильмы в зависимости от жанра, на который пользователь нажимает в компоненте Жанр, или это решение, которое я придумал единственным способом?

Вот мой Redux:

import {createStore, applyMiddleware} from "redux";
import axios from "axios";
import thunk from "redux-thunk";

export const displayGenres = () => {
    return dispatch => {
        axios.get("https://api.themoviedb.org/3/genre/movie/list?api_key=<api-key>&language=en-US").then(response => {
            dispatch({
                type: "DISPLAY_GENRES",
                genres: response.data.genres
            })
        }).catch(err => {
            console.log(err);
        })
    }
}

export const selectedGenre = id => {
    return dispatch => {
        axios.get(`https://api.themoviedb.org/3/discover/movie?api_key=<api-key>&language=en-US&include_adult=false&include_video=false&page=1&primary_release_year=2017&with_genres=9648`).then(response => {
            dispatch({
                type:"SELECTED_GENRE",
                select: response.data.results
            })
        }).catch(err => {
            console.log(err);
        })
    }
}

const reducer = (prevState = {}, action) => {
    switch(action.type){
        case "DISPLAY_GENRES":
            return {
                genres: action.genres
            }
        case "SELECTED_GENRE":
            return {
                select: action.select,
            }
        default:
            return prevState
        }
    }

const store = createStore(reducer, applyMiddleware(thunk));

export default store;

Вот мой компонент Жанры, который отображает все отдельные Жанры на выбор пользователя:

import React, {Component} from "react";
import {connect} from "react-redux";
import {displayGenres} from "./redux";
import {Link} from "react-router-dom";
import Navbar from "./Navbar";

class Genres extends Component {
    constructor(){
        super();
    }

    componentDidMount(){
        this.props.displayGenres();
    }

    render(){

        const mappedGenres = this.props.genres && this.props.genres.map(genre => {
            return (
                    <div className="mappedGenres">
                        <Link to="/showGenres">{genre.name}</Link>
                    </div>    
            )
        })
        return(
            <div>
                <Navbar/>
                <div className="genre">
                    {mappedGenres}
                </div>
            </div>

        )
    }
}

export default connect(state => state, {displayGenres})(Genres);

А вот мой компонент ShowGenresгде я хочу отображать фильмы в зависимости от жанра, на который пользователь нажимает в компоненте жанра:

import React, {Component} from "react";
import {connect} from "react-redux";
import {selectedGenre} from "./redux";
import {displayGenres} from "./redux";


class ShowGenres extends Component {
    constructor(){
        super();
    }

    componentDidMount(){
        this.props.selectedGenre(this.mappedId);
    }

    render(){

        const mappedId = this.props.genres && this.props.genres.map(id => {
            return id.id;
        })

        const mappedSelected = this.props.select && this.props.select.map(genre => {
            return (
                <div>
                    <h1>{genre.title}</h1>
                </div>
            )
        })

        return(
            <div>
                {mappedSelected}
            </div>
        )
    }
}

export default connect(state=> state, {displayGenres, selectedGenre})(ShowGenres);

Ответы [ 2 ]

0 голосов
/ 31 мая 2018

Вот пример.Где-то есть небольшая ошибка, но общая идея есть.Я использовал его раньше, но прошел почти год с момента касания реагировать.Прости за разгильдяйство

const AllMovies = {
  Horror : ['Tax Season', 'Family Dinner', 'DMV Trip 3'],
  Comedy : ['Pasion of the Christ', 'The Earth is Flat'],
  Romance : ['Me, Myself and Bacon', 'There\'s Something About Ice Cream']
}

class Movie
  {
    constructor(title, genre)
    {
      this.genre = genre;
      this.title = title;
    }
  }

class ChildContainer extends React.Component
{
  constructor(props)
  {
    super(props);

  }
  
  GenerateList()
  {
    let output = [];
    for (var genre in AllMovies)
    {
      let movies = AllMovies[genre];
      for (let i = 0; i < movies.length; i++)
      {
        output.push(new Movie(movies[i], genre))
      }
      
    }
    return output.map(movie => {
      return(
        <li onClick={() => this.props.CallParent(movie.genre)}>
          {movie}
       </li>
          )
    })
  }
  
  render()
  {
    return(
      <ul>
        {this.GenerateList()}
      </ul>
    )
  }
}


class ParentContainer extends React.Component
{
  constructor(props)
  {
    super(props);
    
    this.state = {
      CurrentValue : []
    }
    
    this.PropMethod = this.PropMethod.bind(this);
  }
  
  PropMethod(newValue)
  {
    console.log('__GENRE__ : ', newValue);
    let genre = AllMovies[newValue]
    this.setState({
      CurrentValue : genre
    })
  }
  
  render() {
    let genres = this.state.CurrentValue.map(val => {
      return(<li>{val}</li>)
    })
    return(
      <section>
        <ul>
          {genres}
        </ul>
        <ChildContainer
          CallParent={this.PropMethod}
          />
      </section>
    )
  }
}



class App extends React.Component 
{
  constructor(props) 
  {
    super(props);
  }
  


  

  
  render() {
    return(
      <section>
        <ParentContainer/>
      </section>
    )
  }
}


React.render(<App />, document.getElementById('root'));

ОБНОВЛЕНИЕ Теперь должно работать: D

Есть другой способ.Помните, что все эти компоненты являются классами.Вы можете создать экземпляр обоих и передать одну функцию другим реквизитам.Это позволит вам сделать это, не вкладывая их друг в друга.

0 голосов
/ 31 мая 2018

Один из способов сделать это - использовать метод, который принимает входные данные и устанавливает состояние с помощью указанного ввода.Теперь то, куда вы идете с этим, может варьироваться.

Вы можете иметь второй компонент, вложенный в первый, передать метод в качестве реквизита, и для каждого фильма добавьте прослушиватель событий при нажатии, который вызывает методиз реквизита, передавая жанр фильма, который вы щелкнули в качестве параметра.Метод должен быть привязан к родителю, прежде чем он будет передан потомку.

Напишет пример и вскоре опубликует.

...