4 ms·
I'm left scratching my head a bit from this blog post. In https://reactjs.org/docs/concurrent-mode-suspense.html https://reactjs.org/docs/concurrent-mode-suspe
by kansface 7y ago
I'm left scratching my head a bit from this blog post. In https://reactjs.org/docs/concurrent-mode-suspense.html https://reactjs.org/docs/concurrent-mode-suspense.html, current pitfalls of fetching data are explored including waterfalls (sequential loading spinners for nested components) and data races.
The way we currently solve these problems, which for some reason didn't make it into the examples, is with Redux:
fetchProfileData()
const ProfilePage = connect((state) => ({ user: state.user, posts: state.posts})(ProfilePage)
In truth, we'd also track a loading and error state as well. This solution is not subject to data races or waterfalls.
One could argue that their new implementation provides a better interface... but I'm not so sure. The final ProfileDetails won't work outside a Suspend because the Suspense API is Throwing Promises [1]. In fact, it crashes the app :-/
Note how we eliminated the if (...) “is loading” checks from our components. This doesn’t only remove boilerplate code, but it also simplifies making quick design changes.
Yeah, I did note that, but is it a good thing?! Rendering in React is currently localized to the render function of the Component itself! Its rather easy to miss the function call that is throwing a promise during rendering to cause itself to not be rendered! Suspense is a hidden interface to delegate rendering to a parent - perhaps an even more error prone Context API.
All in all, this feels like Hooks to me - the trivial examples in the Docs seem perfectly cromulent, but in practice, the ergonomics are so bad that any time I try to use them, I am forced to spend several hours debugging stuff because they lose predictability when composed. Perhaps this won't be so bad in practice, but I'm having a hard time imagining how to compose components that interact with Suspense. Of course, I'd love to be wrong (about the API) or proven wrong and everything turns out to be magical. Maybe TS makes it perfectly obvious in practice, but maybe it generates a ream of gibberish instead.
The true sleight of hand in most of the examples is to kick off `fetch`ing before a component gets mounted that needs the data:
// Kick off fetching as early as possible
const promise = fetchProfileData();
function ProfilePage() {}...
As far as I can reason, there is no good way to do this. The data dependency graph is naturally defined by the component graph: after all, components know what data they need to render, but that graph can't be resolved until after they are actually rendered. So, you end up defining it in two places with an implicit coupling or via HOC or get a waterfall. I'd be open to some magic here.
1. https://codesandbox.io/s/frosty-hermann-bztrp https://codesandbox.io/s/frosty-hermann-bztrp - see fakeAPI.js (couldn't figure out how to link to it.
- danabramov 7y ago>The way we currently solve these problems, which for some reason didn't make it into the examples, is with Redux: As the author of Redux I can assure that it’s not designed for — or capable of — providing the features described on this page: https://reactjs.org/docs/concurrent-mode-patterns.html https://reactjs.org/docs/concurrent-mode-patterns.html Hope that makes sense. Regarding fetching, as the page says, in practice we use Relay for that. If you want to look at how it works in production, the page does link to Relay docs.
- sktrdie 7y ago> As the author of Redux burnnnnnn
- kansface 7y ago> As the author of Redux I can assure that it’s not designed for — or capable of — the providing thee features described on this page... Hope that makes sense. Sure! Seems like we are talking past each other (these problems being waterfalls and data races and the examples coming from https://reactjs.org/docs/concurrent-mode-suspense.html https://reactjs.org/docs/concurrent-mode-suspense.html).
- danabramov 7y agoI could write a separate comparison of Redux vs Suspense, but it wouldn't make sense to do in React docs because React docs are about... React. Otherwise we'd have to write a comparison for every popular state management solution, which is a lot. If I were to write this comparison, the gist of it would be "Yes, you can solve waterfalls and races, but what's your answer to features on this page: https://reactjs.org/docs/concurrent-mode-patterns.html" https://reactjs.org/docs/concurrent-mode-patterns.html"
- acemarke 7y agoRight, and as a _current_ Redux maintainer, I can also assure you that Redux does nothing to solve those problems :) Redux is simply a synchronous external data store. It does nothing in regards to how you fetch your data. While React-Redux does trigger UI re-renders when the store is updated, we rely on React's own scheduling capabilities to handle actually updating the UI. So, no, Redux definitely does not solve the patterns described in those docs. I'm hopeful that we may be able to eventually build some integrations between Redux and Suspense at some point in the future, but frankly we've been waiting for actual docs and examples of how all this stuff is _meant_ to work. Conveniently, we now actually have some (thanks Dan!), but it's still going to take a long time to absorb what the APIs are and what techniques may be possible.