使用 Reactjs 获取 GET 请求 - 我如何在我的请求中实现可重用的组件来呈现我的数据?
Fetch GET request with Reactjs - how do i implement a reusable component within my request to render my data?
TLDR - 你不应该 implement/call 你的数据获取请求中的可重用组件。这样做的正确方法是让容器组件负责获取数据,将其存储在 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?
我的解决方案
将 <BooksContainer />
作为我的容器组件,书籍数据存储在状态中,并使用 .map
进行迭代,以将每个书籍对象呈现为 <Book />
组件——我们的表示函数。
//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>
)
您应该将 api 的结果存储在状态中,并在 render
函数中呈现 <Book />
。
顺便说一句,最好将组件分开:
- 执行所有逻辑(数据获取,...)的容器。
- 呈现 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} />;
}
}
1) 创建一个容器组件,您可以在其中执行您的 AJAX 请求,然后将结果保存在您的本地状态中,例如 render
方法中的 books
。
2) 将 this.state.books
传递到您的 <Book />
组件中,您可以在其中迭代数组。
3)(可选但推荐)。您可以创建另一个组件,如 <BookDetail />
来呈现单个图书项目
TLDR - 你不应该 implement/call 你的数据获取请求中的可重用组件。这样做的正确方法是让容器组件负责获取数据,将其存储在 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?
我的解决方案
将 <BooksContainer />
作为我的容器组件,书籍数据存储在状态中,并使用 .map
进行迭代,以将每个书籍对象呈现为 <Book />
组件——我们的表示函数。
//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>
)
您应该将 api 的结果存储在状态中,并在 render
函数中呈现 <Book />
。
顺便说一句,最好将组件分开:
- 执行所有逻辑(数据获取,...)的容器。
- 呈现 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} />;
}
}
1) 创建一个容器组件,您可以在其中执行您的 AJAX 请求,然后将结果保存在您的本地状态中,例如 render
方法中的 books
。
2) 将 this.state.books
传递到您的 <Book />
组件中,您可以在其中迭代数组。
3)(可选但推荐)。您可以创建另一个组件,如 <BookDetail />
来呈现单个图书项目