【问题标题】:Fetch GET request with Reactjs - how do i implement a reusable component within my request to render my data?使用 Reactjs 获取 GET 请求 - 如何在请求中实现可重用组件以呈现数据?
【发布时间】:2017-07-25 21:48:03
【问题描述】:

TLDR - 您不应在数据获取请求中实现/调用可重用组件。这样做的正确方法是拥有一个容器组件,该组件负责获取数据,将其存储在state 中,并将其传递给负责将数据呈现为 UI 的展示组件。 (下例)


最初我试图做的事情(我假设组件被转换为 HTML 并且可以创建为字符串 - BAD PRACTICE):

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)
        })

我的问题是
我该如何完成这项工作?如何在 GET 请求中实现我的 Book 组件,以便为数据库中的每个对象呈现可重用的 Book

我的解决方案
&lt;BooksContainer /&gt; 作为我的容器组件书籍数据存储在状态中,并使用 .map 进行迭代,以将每个书籍对象呈现为 &lt;Book /&gt; 组件 - 我们的演示函数。

    //BooksContainer.js - responsible for data fetching and storing
class BooksContainer extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            books: [];
        };
    }
    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({
                    books: data
                });
                console.log('parsed json', data);            
            }, (ex) => {
                this.setState({
                    requestError : true
                });
                console.log('parsing failed', ex)
            })
    }   
    render () {
        return (
            <div className="books-container">
                <ul className="books-list">
                    {this.state.books.map(book => <Book {...book} />}
                </ul>
            </div>
        )
    }

    //Book.js - responsible for presenting each book's data
    const Book = (props) => (
        <li>
            <span className="title">{this.props.title}</span>
            <span className="author">Author: {this.props.author</span>
            <span className="genre">Genre: {this.props.genre}</span>
            <span className="read">Read: {this.props.read ? "Yes" : "No"}</span>
        </li>
    )

【问题讨论】:

    标签: javascript reactjs fetch


    【解决方案1】:

    您应该将 api 的结果存储在状态中,并在 render 函数中呈现 &lt;Book /&gt;

    顺便说一句,分开你的组件会更好:

    1. 执行所有逻辑(数据提取,...)的容器。
    2. 呈现用户界面的演示组件。

    您甚至可以更进一步,使用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} />;
      }
    }
    

    【讨论】:

    • 你能提供一个例子/教程吗?我不确定 OP 会得到它。
    • 我已经考虑过这种可能性并尝试自己这样做,但我无法立即弄清楚。因为 state 每次都存储一个信息,所以它不能单独存储每本书,或者可以吗?那么,正如我的朋友瓦伦丁所说,我很乐意在这项任务中获得任何形式的指导。
    • 编辑后我尝试这样做并得到:“books.map is not a function”错误。
    • 可能你从api接收的数据不是数组,或者是空的?
    • 所以我做了一些检查,并且发生了一些非常奇怪的事情。我 console.log this.state.books,当我不参考演示组件(BookListing)中的数据根本并且控制台显示包含所有书籍的对象时。然后,虽然仍然 console.logging 我的 Books.state.books 我更改了我的代码并在我的 BookListing 组件中以任何方式引用 {books}(例如尝试映射它),控制台显示一个空对象。这里发生了什么?? 编辑我尝试只在 BookListing 中使用 console.log 书籍,控制台再次显示完整的对象。
    【解决方案2】:

    1) 创建一个容器组件,您可以在其中执行 AJAX 请求,然后将结果保存在本地状态,例如 render 方法中的 books

    2) 将 this.state.books 传递到您的 &lt;Book /&gt; 组件中,您可以在其中迭代数组。

    3)(可选但推荐)。您可以创建另一个组件,例如 &lt;BookDetail /&gt; 来呈现单个图书项目

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 2020-04-21
      • 2018-06-28
      • 2018-11-28
      • 1970-01-01
      相关资源
      最近更新 更多