2017-01-20 8 views
0

Source CodeReactを使用して関数内からデータを含むリストをレンダリングする方法は?

タイトルが混乱している場合はごめんなさい。しかし、ソースコードをクリックすると、コンポーネント名Searchがあることがわかります。検索内では、ユーザがレンダー機能内の検索ボタンをクリックするとアクティブになる機能handleSearchSubmitがあります。今私の問題は、trackViewerの中のリストを更新したいということです。すべてのリスト項目には{title}が、<ul>には{trackItems}と表示されます。しかし、私が何をしても、リストを更新するように見えるかもしれません。 thisが含まれていない場合、変数t rackItemsはレンダリング関数内では未定義です。それで私は間違って何をしているのですか?これは、同じファイル内または新しいファイル内のコンポーネントを分離する必要がありますか?

答えて

0

を私が理解から、ここでの目的の動作がAPIからデータを取得し、それを受信したときにそれを表示することです。 Reactの基本的な考え方を理解することが重要です。コンポーネントは、状態または上流の小道具が変更された場合にのみ再レンダリングされます。これはあなたがここに必要なものです。状態の変更を使用して再レンダリングをトリガーします。

import React, { Component } from 'react'; 
import { client_id } from './config'; 
import 'isomorphic-fetch'; 
import 'whatwg-fetch'; 
import SC from 'soundcloud'; 
import ReactDOM from 'react-dom'; 

// This is not a good place for such data, all data should be encapsulated accordingly 
let search = "https://api.soundcloud.com/tracks?&client_id="+ client_id +"&limit=50&offset=0&q="+query; 
let tags = "https://api.soundcloud.com/tracks?linked_partitioning=1&client_id="+ client_id +"&limit=50&offset=0&tags=deep%20house"; 

class Search extends Component{ 

    constructor(props){ 
     super(props); 

     this.state = { 
      value: '', 
      // Moved trackTitle from above into the state 
      trackTitle: [] 
     }; 
    }; 

    handleChange(event){ 
     event.preventDefault(); 

     this.setState({ value: event.target.value }); 
    } 

    handleSearchSubmit(){ 
     event.preventDefault(); 

     // Create local scope buffer for trackTitles to store in state in the end 
     let trackTitleBuffer = [] 

     // You can use shortened expression instead of client_id: client_id, hail ES2015! 
     SC.initialize({ client_id }); 

     // You don't really need query variable, use state directly 
     // Using arrow functions for readability 
     fetch(search + this.state.value, { method:"GET" }) 
     .then(response => response.json()) 
     .catch(error => console.log(error)) 
     .then(json => { 
      json.map(entity => trackTitleBuffer.push(entity.title)) 
      // And pour it all to the state.trackTitle 
      // This is important, you only to want to re-render when you have all the track titles ready 
      // If you pushed the track titles to the state one-by-one, every push would trigger a re-render 
      // It might look cool as well as it might not 
      this.setState({ trackTitle: trackTitleBuffer }) 
     }) 
     .catch(error => console.log(error)) 
    }; 

    render(){ 
     // Desctructuring the state 
     const { trackTitle, value } = this.state 

     return(
      <form> 
      <input type="text" value={this.state.value} placeholder="Enter a Artist, Song, or Album.." onChange={event => this.handleChange(event)}/> 
      <button type="button" onClick={() => this.handleSearchSubmit()}>Search</button> 
      <div id="trackViewer"> 
       <p>Results for: {value}</p> 
       <ul>{ trackTitle.map(title => <li key={title)}>{title}</li>) }</ul> 
      </div> 
      </form> 
     ) 
    }; 
}; 

export default Search; 
+0

このソリューションは、再レンダリングとリスティングの両方の問題を解決してくれてありがとうございます。 。 –

0

あなたはtrackItems変数を廃止する、あなたのレンダリング機能

const trackItems = trackTitle.map((titles) => 
      <li>{titles}</li> 
     ); 

だから、クイックフィックス内部this.trackItemsを介してアクセスすることはできませんのでごtrackItems変数は、あなたのクラスに接続されていないローカル変数でありますであるとして完全にし、代わりにあなたのレンダリング関数内でそのコードスニペットを実行します。

render(){ 
    return(
     <form> 
     <input type="text" value={this.state.value} placeholder="Enter a Artist, Song, or Album.." onChange={this.handleChange}/> 
     <button type="button" onClick={this.handleSearchSubmit}>Search</button> 
     <div id="trackViewer"> 
      <p>Results for: {this.state.value}</p> 
      <ul>{trackTitle.map((titles) =><li>{titles}</li>)}</ul> 
     </div> 
     </form> 
    ) 
} 
+0

コードを更新して表示するように更新しましたが、提案した内容を試してみましたが、まだ表示されていません。コンソールでは、値が空で何かを表示する必要があることがわかります。 –

+0

私は実際に動作させることができましたが、奇妙なバグが発生しています。入力をクリックして何かを入力するまで、リストに実際に結果が表示されない場合は、フォームタグの内部にあると思われます。 –

関連する問題