2017-06-24 22 views
0

Reactの他の子コンポーネントに状態を渡す方法を理解できません。私のコードでは、入力を受け取り、それを私の状態配列にマップするコンポーネントがあり、そのデータの一部を別のコンポーネントに表示しています。これはうまく動作しています。Reactの複数の子コンポーネントに状態を渡す

しかし、全体的な目標は、ユーザーがリストに追加したアイテムをクリックすると、React Routerが起動して、titleのように入力した追加の情報を持つMovieDetailsコンポーネントにビューを変更することです、日付と説明。

MovieDetailsコンポーネント内の状態に正しくアクセスできないようなので、私はリアクションルータを設定することさえできませんでした。そして、私はルータで正しいMovieDetailsコンポーネントをどのように表示するかについてはあまりよく分かりません。私は右のそれを得た場合

import React, { Component } from 'react'; 
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'; 
import './App.css'; 

class App extends Component { 
    constructor() { 
    super(); 
    this.addMovie = this.addMovie.bind(this); 
    this.state = { 
     movies : [] 
    }; 
    } 

    addMovie(movie) { 
    let movies = this.state.movies; 
    movies.push(movie); 
    this.setState({ movies }); 
    } 

    render() { 
    return (
     <div className="wrapper"> 
     <div className="container"> 
      <div> 
      <h3 className="heading">Favorite Movies</h3> 
      </div> 
     </div> 
     <div> 
      <AddMovie addMovie={ this.addMovie }/> 
      <MovieList movies={ this.state.movies }/> 
     </div> 
     </div> 
    ) 
    } 
} 

class AddMovie extends Component { 
    addMovie(event) { 
    event.preventDefault(); 
    const movie = { 
     title : this.title.value, 
     year : this.year.value, 
     image : this.image.value, 
     desc : this.desc.value 
    } 
    this.props.addMovie(movie); 
    this.movieForm.reset(); 
    } 
    render() { 
    return (
     <div className="container"> 
     <form ref={(input) => this.movieForm = input} onSubmit={(e) => this.addMovie(e)}> 
      <input ref={(input) => this.title = input} className="Input" type="text" placeholder="Title"/> 
      <input ref={(input) => this.year = input} className="Input" type="text" placeholder="Year"/> 
      <textarea ref={(input) => this.desc = input} className="Input" type="text" placeholder="Description"></textarea> 
      <input ref={(input) => this.image = input} className="Input" type="text" placeholder="Poster URL"/> 
      <button type="submit">Add</button> 
     </form> 
     </div> 
    ) 
    } 
} 

class MovieList extends Component { 
    render() { 
    return (
     <div> 
     { this.props.movies.map((movie, i) => <MovieListItem key={i} details={ movie }/>)} 
     </div> 
    ); 
    } 
} 

class MovieListItem extends Component { 
    constructor(props) { 
    super(props); 
    this.toggleClass = this.toggleClass.bind(this); 
    this.state = { 
     active: false 
    }; 
    } 
    toggleClass() { 
    const currentState = this.state.active; 
    this.setState({ active: !currentState }); 
    } 
    render() { 
    const { details } = this.props; 
    return (
     <div 
     className={this.state.active ? "red": null} 
     onClick={this.toggleClass} 
     > 
     <img src={details.image} alt=""/> 
     <hr/> 
     </div> 
    ) 
    } 
} 

class MovieDetails extends Component { 
    render() { 
    return (
     <div> 
     <p>title here</p> 
     <p>year here</p> 
     <p>description here</p> 
     <img src="image" alt=""/> 
     </div> 
    ) 
    } 
} 

export default App; 
+0

Iから完全setState APIを参照してください:あなたは、現在の状態を使用していますsetState何か、あなたが代わりにコールバックを使用する必要があります

const movie = { title : this.title.getDOMNode().value, year : this.year.getDOMNode().value, image : this.image.getDOMNode().value, desc : this.desc.getDOMNode().value }; ... this.movieForm.getDOMNode().reset(); 

他の事、あなたの問題がどこにあるのか本当に理解していない。あなたはスニペット、またはcodePenを作ろうと思いますか? – soywod

+0

私は分を取ったし、それは正しく動作していないが、ここでそれはCodePenにある:https://codepen.io/anon/pen/jwLoaq?editors=0010申し訳ありません! – joehdodd

答えて

0

は、あなたがMovieListから作成された項目をクリックしているとき(detailsにアクセスする必要があります)新しいコンポーネントにプッシュしたいですか?もしそうなら、ここにあなたがしなければならない手順です:あなたは新しいビューをプッシュしたい場合

  1. が、あなたは「反応し、ルータを」からbrowserHistoryまたはhashHistoryのようなものを使用する必要があります。この場合はbrowserHistoryを使用します。
  2. MovieDetailsの状態にアクセスするには、browserHistoryに渡します。ここで

MovieListコンポーネントから項目がクリックされたときに、私は新しいビューにプッシュするようにコードを使用する方法です。

import {Router, Route, browserHistory} from "react-router"; 

class Routes extends Component { 
    render() { 
    let props = this.props; 

    return (
     <Router history={browserHistory}> 
     <Route path="/" component={App}/> 
     <Route path="/movie-details" component={MovieDetails}/> 
     </Router> 
    ) 
    } 
} 

// Here is your App component 
class App extends Component { 
    // ... your code 
} 

// ... your other classes 


class MovieListItem extends Component { 
    // ... Constructor 
    // Here I'm pushing the new route for MovieDetails view 
    toggleClass(details) { 
    browserHistory.push({ 
     pathname: '/movie-details', 
     state: details // pass the state to MovieDetails 
    }); 
    // ... your code 
    } 

    render() { 
    const {details} = this.props; 

    return (
     <div 
     // ... your code 
     onClick={this.toggleClass.bind(this, details)} // pass details to toggleClass() 
     > 
     // ... your code 
     </div> 
    ) 
    } 
}  

// Here is your Movie Details component 
class MovieDetails extends Component { 
    console.log('This props: ', this.props.location.state); // The details object should be logged here 
    // ... your code 
} 

// Export Routes instead of App 
export default Routes; 

役に立てば幸い!

+0

うーん...どこに行くのか分かりますが、試してみましたが、今度は、のMovieDetailsコンポーネントを読み込み、テストコンテンツをページに表示しています。私はそれをホームページに強制することはできません - MovieDetailsのパスをロードし続けます。 また、MovieDetailsのMovieListItemデータにアクセスしようとすると、エラーが発生します。 – joehdodd

+0

もう一度、あなたの流れが正しいと確信していますか?ここには[.gif](https://www.dropbox.com/s/vfsx364cer6kse5/20170624_192319.gif?dl=0)があり、そこには 'MovieDetails'コンポーネントで受け取ったフローとプロップを見ることができます。 'toggleClass'がclickイベントからバインドされるように私のコードを編集しました。また、私は 'MovieDetails'コンポーネントに受け取られるべき状態に穴のパスを記録しました。 –

+0

ああ!ワオ。できます。 OK、私は 'match.params'を使って動作させてIDを取得し、それを変数に代入し、それを自分の状態の配列インデックスとして渡しました。 – joehdodd

0

問題は、入力値にアクセスしようとする方法に起因します。 refを使用すると、実際のDOM要素ではなくReactラッパーが取得されるため、.valueまたは.reset()に直接アクセスすることはできません。 DOM要素を取得するには、getDOMNode()メソッドを使用する必要があります。これが私の仕事:

addMovie(newMovie) { 
    this.setState(({movies: prevMovies})=> ({ 
    movies: [...prevMovies, newMovie] 
    })); 
} 

official doc

+0

ありがとう!さて、配列インデックスを使用すると、MovieDetailsコンポーネント内の配列のデータにアクセスできるようです。今私は、ユーザーがクリックするムービーリスト項目からの対応するデータでMovieDetailsコンポーネントを表示するためにルーターを使用する方法を理解しようとしています。 – joehdodd

+0

公式の文書を参照してください、それはかなり明確です。 <ルートパス= "/リスト"コンポーネント= {ムービーリスト} />のような正しいルートでコンポーネントを接続するだけで、 ' – soywod

関連する問題