5 ms·
I wish React would come with a standard way to handle Ajax (or a convention or semi-standard library would emerge). (Edit: "comes along" in the sense that immut
by captainmuon 9y ago
I wish React would come with a standard way to handle Ajax (or a convention or semi-standard library would emerge). (Edit: "comes along" in the sense that immutability-helpers, redux and create-react-app come along with react. I'm not proposing to add anything to the react module. I'm not the world's best expert on react, but before downvoting can you please assume I know a little bit of what I'm talking about?)
Something that:
- Can fetch JSON according to criteria from an API
- Caches stuff locally (just in memory, or in local storage) in case of duplicate calls
- Deals with multiple concurrent calls, and merge them (e.g. fetching 1 and then 2,3,4 before 1 finishes -> either cancel 1, or wait until it finishes, and then fetch only the last requested item.
- And all the stuff I can't think about right now, like cancellation and timeouts
Plug your pure component into one of these, tell it about your API, and you're done. It's really error prone to write these containers yourself. And I think Redux doesn't really help much with Ajax.
- fokinsean 9y agoThis is one thing I miss about Ember. We recently moved to React and I'm really starting to miss Ember Data (even though it can be very picky).
- k__ 9y agoI plan to use it in a React-Native app for a JSON/REST API. Why not, isn't it standalone?
- spicyj 9y agoI haven't used Ember Data much. I'd be curious how you think it could apply or could be ported to React. Maybe you'd have time to write up a short gist of what you wish you could write in React?
- vasilakisfil 9y agoYes Ember-Data was great thing to have in Ember, something I miss from React ecosystem. In the early days was a bit unstable but now it's super stable and flexible (serializers/adapters customization etc). I think there should be an initiative to get it out of Ember so that you can use it with other projects as well.
- peller 9y agoBut React isn't a framework. It's only a view library. So by definition, it shouldn't care less about Ajax. Similarly, Redux is only a state-management container. It also shouldn't care about Ajax. What you're probably looking for is redux-saga[0]; it provides the tools to let you easily write all the fancy functionality you're talking about. [0] https://redux-saga.js.org/ https://redux-saga.js.org/
- icebraining 9y agoShouldn't the browser be doing the caching? Now that they even have the Fetch API, which can return actual JSON objects, they could even cache them pre-parsed.
- captainmuon 9y agoThat would be ideal. But my data takes a few hundred ms to be computed on the server per data point. So when I start up, the server sends all data it already computed before, compressed, in one request. Then the response for data point 123 is not in the browser cache for `/api/points/123`, but maybe it is in `/api/points/precalculated`. My code then shouldn't care if the data came in the initial prefetch, or a later fetch, or is fetched in real-time, or even computed on the client. Just: let res = await fetchData('setting', 123); this.setState({property: res.property}); This is what I'm currently doing. I think there could be a library that helps you to write `fetchData`. Or maybe you'd have a special react container that you'd just wire up appropriately.
- thatswrong0 9y agoReact _is_ only a view library. It shouldn't have any thing to do with things like Ajax - that's part of what makes it simple to work with l. It does one thing and does it well. It doesn't even seem to be the responsibility of Redux, which more so is consider with prescribing _how_ data and actions flow through your system, not how exactly those calls touch the outside world. I don't like employing the phrase "separation of concerns" that often / without serious thought, but this is seems to be a valid use case for it. Presentation components shouldn't care about how fetches data, they should ideally just be a function of their props. Even container components should only care about what data they are accessing, not how it comes to be in the data store. What you're asking for could just be a plain JS library - when you ask for certain routes in your app, fetch some data. When it comes in, handle all those edge cases you describe. Update the data store. When that happens, we're finally back in Redux land. It doesn't care about how you fetch your data, all it cares about is _that_ you touched it at all.
- thatswrong0 9y agoI do think that there is some kind of implicit framework living within a smart combination React, Redux, and Immutable.js that combined with something like Uncle Bob's clean architecture could probably become a standard within the React world. My company is maybe 50% of the way there towards such a thing, and it really is a pleasure to work with.
- acemarke 9y agoThis relates to the discussion I've been trying to have on potential abstraction layers that could be built on top of Redux to make it easier for some people to learn and work with [0]. There ARE a large number of existing libraries out there for things like fetching and managing normalized entities [1], as well as some more extensive frameworks like `dva` [2]. I'd be interested in hearing more details about what your company has put together. If you get a chance, please drop by the Reactiflux chat channels [3] and ping me. [0] https://github.com/reactjs/redux/issues/2295 https://github.com/reactjs/redux/issues/2295 [1] https://github.com/markerikson/redux-ecosystem-links/blob/master/entity-collection-management.md https://github.com/markerikson/redux-ecosystem-links/blob/ma... [2] https://github.com/dvajs/dva https://github.com/dvajs/dva [3] https://www.reactiflux.com https://www.reactiflux.com
- 18nleung 9y agoThis sounds like a good use case for Promise.all() and fetch: const first = fetch(endpoint1); const rest = Promise.all([ fetch(e2), fetch(e3), fetch(e4), ]); // cancel here const json1 = await first.json(); const json234 = await rest.json(); While native promises can't cancel on their own, with a library like Bluebird you can get that functionality.
- captainmuon 9y agoYes! Promises and window.fetch are nice, that's what I based my code on. I am thinking about switching to axios (or Bluebird) to get cancellation, though. But this is just the low-level code. Instead of (pseudocode): window.fetch('/the/api/url') .then(res => res.json()) .then(json => this.setState({thing: json['thing']})); I do (something like): fetchFromServerOrCache('param', 123) .then(obj => this.setState({data: data})); The minor difference is that I do some processing (ok, you can do that somewhere is), but the main thing is the caching. The user can drag a slider bar and select different 'frames', and I don't want to transmit everything again if the frame was already selected. For various reasons I can't rely solely on the browser cache. One reason is that I prefetch all frames the server already computed at the beginning. So I want to check if the frame is available from the initial batch, or a subsequent fetch, and if not, fetch it in place. I wrap it into a promise so the calling code does not need to know about the caching. I then pass the state to a child component which is as pure as possible.
- _greim_ 9y agoShameless self-plug. I developed a design pattern I call "vacancy observers" that solves a subset of the Ajax problem. Basically, fetching data for display; AKA the "R" in CRUD. My POC implementation is on Github. https://github.com/greim/motel https://github.com/greim/motel
- 0xCMP 9y agoRelay is what is supposed to be doing this for React. I highly recommend Relay if you have a graphql api to talk to. I had to fight it initially (the docs are not good enough, although better than before, and I need to contribute what I learned) but once I got going it's made what took an incredible amount of time in Mobx, Redux, or Flummox much easier.
- cel1ne 9y agoI have a network-state in every application, usually as a set of "NetworkRequests", which are data-object that describe a request. Just like I sync the UI-state to the browser using React, I sync the network-state to the network by a) using a custom NetworkManager, that takes a set of requests and syncs it with currently running requests. b) using react itself. In a simple project I created a ReactComponent for every network-request. The render() is just an invisible div, the actual requests get started and stopped in componentDidMount() and other life-cycle hooks. This approach works everywhere, it is serialisable and easy to think about. I tend to write the redux-part ("controller") of my applications myself, it's seldomly more than 100 lines and more adaptable to my needs. And I never use immutable.js, it's really unnecessary and slows down development-speed (via it's weird api) and runtime-performance.