-
-
Notifications
You must be signed in to change notification settings - Fork 26.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add docs for using Promises and making AJAX requests #531
Conversation
Thank you for your pull request and welcome to our community. We require contributors to sign our Contributor License Agreement, and we don't seem to have you on file. In order for us to review and merge your code, please sign up at https://code.facebook.com/cla - and if you have received this in error or have any questions, please drop us a line at cla@fb.com. Thanks! |
Thank you for signing our Contributor License Agreement. We can now accept your code for this (and any) Facebook open source project. Thanks! |
template/README.md
Outdated
@@ -23,6 +23,8 @@ You can find the most recent version of this guide [here](https://github.com/fac | |||
- [Adding Custom Environment Variables](#adding-custom-environment-variables) | |||
- [Integrating with a Node Backend](#integrating-with-a-node-backend) | |||
- [Proxying API Requests in Development](#proxying-api-requests-in-development) | |||
- [Using Promises](#using-promises) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let’s make this one section: Fetching AJAX Requests
. Let’s also put it before Integrating with a Node Backend
.
template/README.md
Outdated
|
||
This project includes a [fetch polyfill](https://github.com/github/fetch), which makes it easier to make web requests. | ||
|
||
The `fetch` function allows to easily makes AJAX requests. It takes in a URL as an input and returns a `Promise` that resolves to a `Response` object. You can find more information about `fetch` [here](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's say "the global fetch function" instead to make it clear you don't need to import it.
template/README.md
Outdated
|
||
You can make a GET request like this: | ||
```javascript | ||
class MyComponent extends Component { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add all necessary imports here so people can copy and paste. Same in next block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we make this a drop-in replacement for App.js that ships with this project? Instead of UserGists maybe map over their names in a <ul>
.
template/README.md
Outdated
const { string } = PropTypes; | ||
|
||
class RepoList extends Component { | ||
static propTypes = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove propTypes. Not essential to this example and introduces class properties which we don't want for now.
Please consider https://github.com/smalldots/smalldots#fetch :) |
template/README.md
Outdated
fetch(`https://api.github.com/users/${user}/repos`) | ||
.then((response) => response.json()) | ||
.then((repos) => this.setState({ repos })) | ||
.catch((error) => console.log('Error', error)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a subtle problem here. If setState() throws (for example due to an error in render()), we will get into the catch handler. It is then easy to miss or ignore that error, and now React is in an inconsistent state.
Instead, let's put catch() before the second then(). This way we only catch network errors. We want errors in setState() to stay unhandled.
Let's make catch() return an empty array. Then we can safely use its result in setState() whether it succeeded or failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also note that fetch
doesn't reject/throw for an error status, so if GitHub is down and you get a 503
status, or if you get rate limited and they return 403
, none of these errors will end up in the catch()
– setState()
gets called with the parsed JSON body of the error response.
So to handle HTTP errors, you'll also have to check response.status
, e.g. response.status >= 200 && response.status < 300
(response.ok
is a handy shortcut for that), and treat a non-OK status as an error.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, @insin mentioned this later in a comment too. We should handle both !ok
and actual errors in the same way, that is, by showing the message.
template/README.md
Outdated
} | ||
|
||
componentDidMount() { | ||
this.fetchRepos(this.props.user); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If the person copies and pastes this component into App.js, user prop will be undefined. Can you make it so this is actually copy and pasteable with no modifications?
I would suggest that, rather than display repos by user, let's display stargazers of facebook/react repo. Then we can hardcode it.
Thank you so much for bearing with me and making these changes. I want to make this really good. 👍 |
Should this include examples of displaying a loading indicator and suitable error messages on failure? e.g. if you're rate-limited - which can happen very quickly with unauthenticated GitHub API calls - |
Yes, this sounds like a great idea. Let's do it. |
Hey! I'm so sorry for the late response, I've been really busy... Sorry once again |
I tried to keep it at simple as possible since I'm a bit worried that the loading and error handling might introduce noise to the example |
@gaearon just a friendly ping 😄, I'm more than happy to do any changes needed! |
Sorry I left this hanging. I was very busy with React in the past few months, and so I left some PRs neglected. We tried to do something similar in React docs, and it didn’t go well. See the discussion in facebook/react#8098. There are so many possible edge cases and race conditions, all because I’m not sure we should add examples that might set users on the wrong path. At this point I have a lot of doubts about What do you think? |
In my experience axios is a better option. Fetch can be considered lower level |
CRA does polyfill |
Latest specification for fetch adds cancelation. Would be nice to see example of cancel. |
Thanks again. I'm sorry we didn't reach consensus here and let it slide. |
#521 This adds some simple documentation for the fetch and Promise polyfills.
@gaearon Should we also add a simple example of how to use this with React? Or do you think it falls out of scope?