News for hackers. Stuff that matters.
Re:Simple React Patterns by jbaudanza on Friday November 10, 2017 @02:17AM (#15668482)
The problem with resolving promises inside of `componentDidMount` is that there is no way to cancel those promises. If the component is unmounted, and then setState is called, it will generate an error (or a warning. I can't remember).

Facebook discusses this on its blog: https://reactjs.org/blog/2015/12/16/ismounted-antipattern.ht...

I've been using Observables which, in my experience, bind a little cleaner than Promises to React components.

Re:Simple React Patterns by Guillaume86 on Friday November 10, 2017 @03:25AM (#15668669)
Yes there was a whole discussion in a github issue about the correct pattern to solve this. Creating and guarding against a `isMounted` field in your `.then()` callbacks means you prevent garbage collection of the unmounted components. An easy solution is to use cancellable promises (with some subtleties to allow garbage collection). There's an implementation which take care of this properly here (provides an HoC): https://github.com/hjylewis/trashable-react .
Re:Simple React Patterns by loevborg on Friday November 10, 2017 @04:26AM (#15668839)
When you say "cancellable promises", that means that you cannot use native JS promises, correct?
Re:Simple React Patterns by Guillaume86 on Friday November 10, 2017 @06:05AM (#15669148)
You can, you just need to wrap it when used inside a react component.
Re:Simple React Patterns by drdaeman on Friday November 10, 2017 @07:37AM (#15669443)
How?

I've thought it's just technically impossible (no API to do so) to cancel a `fetch` request in progress.

Re:Simple React Patterns by Guillaume86 on Friday November 10, 2017 @08:53AM (#15669841)
We're talking about several different things:

Native promises do not have a "real" cancellation API (no 3rd path besides resolved and rejected) but you can mimic the functionality by rejecting with a dedicated error type, or use another promise as a cancellation token for example.

fetch(), which uses promises as return type, do not support aborting requests, as discussed [here](https://github.com/whatwg/fetch/issues/447) but the [old XMLHttpRequest does](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequ...).

Aborting is specific to HTTP requests, it's stopping the connection to the remote server (so technically impossible to implement with the current APIs as you said). Cancelling a promise is just stopping all onResolved continuations to be called, so it can be implemented in several different ways as I explained above.

The end result if you use a classic cancellation wrapper on a fetch() promise is that the onReject continuations will be called immediately with a specific reason. The HTTP request will continue to the end (no abort), but the response will be ignored.

In the case of the react library I mentioned, both the onResolved and onReject continuations will be ignored if cancelled, it's the subtlety that allows the component to be garbage collected (and probably why the author decided to call that "thrashable" as opposed to "cancellable" to mark the difference).

Re:Simple React Patterns by always_good on Friday November 10, 2017 @11:05AM (#15670771)
For example, you can wrap a promise such that when it finally resolves, it checks an isCancelled flag and rejects instead so that your .then callbacks aren't run.

It's not about cancelling any potential inflight action within the promise itself.

In this case, you don't want the callback to run after the react component unmounts, nor do you want to hold a reference to the component:

    promise
        .then(value => this.setState({ value }))
Re:Simple React Patterns by myhf on Friday November 10, 2017 @08:17AM (#15669636)
You don't have to cancel the fetch request, you just have to cancel its callback.
Re:Simple React Patterns by rounce on Friday November 10, 2017 @08:06AM (#15669576)
Promises? Cancellation? The whole point of a Promise is that it must resolve to something eventually.
Re:Simple React Patterns by ryanbrunner on Friday November 10, 2017 @09:49AM (#15670174)
You're cancelling the promise from the perspective of the caller, not the Promise itself. Promises themselves can't decide that they don't want to resolve, but there's plenty of cases where whoever requested the promise in the first place is no longer interested in the results.
Re:Simple React Patterns by FLUX-YOU on Friday November 10, 2017 @08:32AM (#15669724)
Where is the typical place to put initial fetches? I've been setting empty state and then calling a method at the end of a constructor which ultimately results in a promise that calls setState with the data.

But I would never do something like that in, say, the constructor of a WPF/UWP windows app as those have "Loaded" or "Loading" events of some kind (which is parallel to componentDidMount).

Re:Simple React Patterns by ihsw2 on Friday November 10, 2017 @09:20AM (#15669996)
`componentDidMount`, which is after a React component has been rendered. This contradicts the parent commenter directly but I'm fine with that.

The React lifecycle has `componentDidMount` for doing stuff (at most once) after rendering.

Re:Simple React Patterns by always_good on Friday November 10, 2017 @11:02AM (#15670733)
I don't understand what you're saying.

Once the component mounts, then it can be unmounted. The upstream comment is talking about when you have a promise that is still running after unmount.

Re:Simple React Patterns by parmesan on Friday November 10, 2017 @08:27AM (#15669696)
In Android (for example), one would use an observable stream bound to the lifecycle of the host. Most folks do this using Rx and add a custom operator for unsubscribing on the host DESTROY event.
Re:Simple React Patterns by pcmaffey on Friday November 10, 2017 @09:26AM (#15670038)
Protect the setStates in the callback with a conditional switch that gets flipped off in componentWillUnmount.
Re:Simple React Patterns by whistlerbrk on Friday November 10, 2017 @11:05AM (#15670774)
Not clear on what you're saying, pseudocode?
Re:Simple React Patterns by topgunsarg on Friday November 10, 2017 @11:10AM (#15670820)
In componentWillUnmount, set a var componentUnmounted true. In componentDidMount in the callback for the fetch, check for componentUnmounted before setting state for an error or whatever you want to do.
Re:Simple React Patterns by travmatt on Friday November 10, 2017 @12:40PM (#15671494)
Set a variable... set a property in the component state? Or set a static variable on the class?
Re:Simple React Patterns by pcmaffey on Friday November 10, 2017 @01:04PM (#15671684)
I use a static var on the class.

  componentDidMount() {
   if (!this.unmounted) ...
  }

  componentWillUnmount() {
   this.unmounted = true
  }
Re:Simple React Patterns by fatso83 on Saturday November 11, 2017 @05:43AM (#15675794)
That's not a static car on the class. It's on the instance! A static class property would entail something like `Foo.unmounted = true` (a bad idea).
Re:Simple React Patterns by k__ on Friday November 10, 2017 @07:22AM (#15669403)
it would be nice if React.Component had a cancel method, so you could simply drop all your promises into it and they get canceled when the component unmounts.

    this.cancelOnUnmoun(new Promise(...)).then(...)