2017-07-25 26 views
1

我一直在用API練習一段時間,創建了我自己的書籍API來練習。我已經制作了一個全功能庫,所有的Ajax請求都可以正常工作,只使用html和JavaScript-ES6。我繼續研究Reactjs,並嘗試使用React構建相同的庫。所以當涉及到處理API時,我聽說取回是一種選擇。 所以這是使用取我的GET請求:使用Reactjs獲取GET請求 - 如何在我的請求中實現可重用組件以呈現我的數據?

fetch('http://localhost:8000/api/Books') 
     .then(response => { 
      if (!response.ok) { 
       throw Error('Network request failed.') 
      } 
      return response; 
     }) 
     .then(data => data.json()) 
     .then(data => { 
      let output = '' 
      for (let book of data) { 
       output += (
        <Book id={book._id} 
          title={book.title} 
          author={book.author} 
          genre={book.genre} 
          read={book.read} /> 
        ); 
      } 
      console.log('parsed json', data); 
      document.getElementById('database').innerHTML = output; 
     }, (ex) => { 
      this.setState({ 
       requestError : true 
      }); 
      console.log('parsing failed', ex) 
     }) 

,你可以看到,該表成分那裏是獲得信息和道具是父「LibraryProject」組件的子組件。本書看起來像這樣:

class Book extends React.Component{ 
constructor (props){ 
    super(props); 
    this.state = { 
     edit : false 
    } 
} 
render() { 
    return (
     <li data-id={this.props.id}> 
      <p><span className="noedit title">{this.props.title}</span> 
       <input type="text" className="edit title"/> 
      </p> 
      <p>Author: <span className="noedit author">{this.props.author}</span> 
       <input type="text" className="edit author"/> 
      </p> 
      <p>Genre: <span className="noedit genre">{this.props.genre}</span> 
       <input type="text" className="edit genre"/></p> 
      <p>Read: <span className="noedit read">{this.props.read?"Yes":"No"}</span> 
       <input type="checkbox" 
         className="edit read" 
         value={this.props.read?"true":"false"}/> 
      </p> 
      <button data-id={this.props.id} className='remove'>Delete</button> 
      <button className="editBook noedit">Edit</button> 
      <button className="saveEdit edit">Save</button> 
      <button className="cancelEdit edit">Cancel</button> 
     </li> 

    ) 
}} 

它預計有編輯和刪除功能,因此它的結構。

現在,當用戶點擊一個按鈕時正在進行調用,因此不使用componentDidMount或任何其他生命週期,該請求只是在handleClick函數中實現。你可以看到,我console.log數據中的請求。和那個問題開始的地方。數據顯示完美在控制檯 - 每個對象及其屬性的詳細:

http://i.imgur.com/LiVRgjw.png

所以數據被正確收到,並與API本身沒有問題。問題是,當我看到的是[對象的對象]的網站是這樣的:

http://i.imgur.com/Q5jYwp2.png

我試圖換書一個div裏面,也只是book.title例如一個div,以看看問題是否與組件渲染有關,但我得到了同樣的結果。 只有當我將輸出設置爲普通book.title,沒有div或花括號時,我纔會一個接一個地看到標題。

.then(data => { 
      let output = '' 
      for (let book of data) { 
       output += (
        book.title 
        ); 
      } 

所以我的問題:我如何使這項工作?如何在GET請求中實現我的Book組件來爲數據庫中的每個對象呈現可重用的Book?

我在網上搜索了幾天,找不到答案。 我相信這是一個非常基本的障礙,我不是唯一面對它的人。 非常感謝您的幫助,期待您的建議!

編輯#1 從我到目前爲止,這是需要將數據從容器組件的狀態GET請求存儲和傳遞下來的表象組件作爲道具的經驗教訓。在我的情況下,它是在LibraryProject組件內的componentDidMount()中調用請求,並將其作爲道具傳遞給負責呈現信息的Book組件。

//LibraryProject.js 

    componentDidMount() { 
      fetch('http://localhost:8000/api/Books') 
       .then(response => { 
        if (!response.ok) { 
         throw Error('Network request failed.') 
        } 
        return response; 
       }) 
       .then(data => data.json()) 
       .then(data => { 
        this.setState({ 
         content: data 
        }); 
        console.log('parsed json', data); 

       }, (ex) => { 
        this.setState({ 
         requestError : true 
        }); 
        console.log('parsing failed', ex) 
       }) 
     } 
     render() { 
      return (
      <div> 
       ... 

       <div className="book-filter"> 
        <button id="search-books" 
          onClick={this.handleSearch.bind(this)}> 
          Search for books 
        </button> 
        ... 

       <div id="database"> 
        {this.state.database ? <Book list={this.state.content} /> : <h4>Books will be shown here...</h4>} 
        {this.state.requestError ? <h4>Failed to get the data. Please check the log for errors.</h4> : ''} 
       </div> 
      </div> 
     ) 
    } 

    //Book.js 
    class Book extends React.Component{ 
     constructor (props){ 
      super(props); 
      this.state = { 
       list : this.props.list 
      } 
     } 
     render() { 
      let list = this.state.list; 
      for (let book of list){ 
       return(
        <li key={book._id}> 
         <p><span className="noedit title">{book.title}</span> 
          ... 
        </li> 
       ) 
      } 
     } 
    } 

現在的問題是,我只得到一個項目從名單',這是一個對象數組呈現 - [{},{},{}]。 任何想法爲什麼?

編輯#2 - 最後 好吧,所以我設法使這一切工作。 顯然,根據React文檔:「如果語句和for循環不是JavaScript中的表達式,那麼它們不能直接在JSX中使用」。 所以這裏的什麼作品:

 //Book.js 
    class Book extends React.Component{ 
     constructor (props){ 
      super(props); 
      this.state = { 
       edit : false, 
       list : this.props.list 
      } 
     } 
     componentWillReceiveProps(nextProps) { //for Updating 
      if (nextProps.list !== this.state.list) { 
       this.setState({ list: nextProps.list }); 
      } 
     } 
     render() { 
      return(
       <div> 
        {this.state.list.map((book) => 
         <li key={book._id}> 
          <p><span className="noedit title">{book.title}</span> 
           ... 
         </li> 
        )} 
       </div>) 
     } 
    } 

我沒使用被.MAP作爲表達我的內部渲染功能和包裹在一個div。 希望這有助於任何人,謝謝@哈賈的幫助。

回答

1

您應該將api的結果存儲在狀態中,並在render函數中呈現<Book />

順便說一句倒不如分開你的組件:

  1. 該做的所有邏輯容器(數據抓取,...)。
  2. 呈現UI的表示組件。

,您甚至可以通過使用redux處理全局狀態走得更遠,並redux-saga處理的副作用(API調用)

編輯

這裏是一個小例子。

表象的成分:

const BookListing = ({ books }) => (
    <ul> 
    {books.map(book => <li key={book.id}>{book.title}</li>)} 
    </ul> 
); 

容器組件:

class Books extends Component { 
    constructor(props) { 
    super(props); 
    this.state = {books: []}; 
    } 
    componentDidMount() { 
    fetch('http://localhost:8000/api/Books') 
     .then(data => data.json()) 
     .then((data) => { this.setState({ books: data }) }); 
    } 
    render() { 
    return <BookListing books={this.state.books} />; 
    } 
} 
+0

您可以提供一個示例/教程嗎?我不確定OP會得到它。 –

+0

我曾考慮過這種可能性,並試圖自己做這件事,我無法馬上知道。因爲國家每次存儲單個信息都不能單獨存儲每本書,或者可以嗎? 那麼,作爲我的朋友,瓦朗蒂娜說,我很樂意接受這項任務的任何指導。 – Amiry

+0

*編輯後*我試圖做到這一點,並得到:「books.map不是一個函數」錯誤。 – Amiry

0

1)創建一個容器組件,你可以做你的AJAX請求,然後將結果保存在你的當地的國家,在render方法中說books

2)將this.state.books傳遞到您的<Book />組件,您可以遍歷該數組。

3)(可選但建議)。您可以創建另一個組件,例如<BookDetail />以呈現單個圖書項目