Hacker News new | past | comments | ask | show | jobs | submit login
Firebase as a React Hook (pragli.com)
126 points by dsaffy on Jan 15, 2020 | hide | past | favorite | 42 comments



This is the kind of stuff that makes me really love hooks. I've been able to refactor so much code cleanly -- complicated data fetching logic, ugly parts of my Redux store, confusing HOCs, window.setInterval spaghetti, etc. Really excited to see more high-level hooks get published.


I tend to be "behind" on the latest and greatest in my frontend Dev work. Usually picking stuff up 1 or 2 years after the initial hype.

I do have to say that I am eyeballing hooks for solving HOCs, which have been popping up more and more in my applications.


This is a great strategy in many ways, because after a couple of years the 'this solves every problem' hype has mostly settled and the good, practical uses for the newer pattern are usually fairly clear from consensus.

I'd say use this to your advantage with hooks. They're amazing and much nicer for some things, but don't go in thinking of HOCs, render props, even class components with lifecycle methods, as something that should be replaced entirely because hooks are universally better at everything they can do.

The latter are indeed cleaner than hooks, simpler, less hassle, etc in many situations - and truly, honestly, a lot of the time it's nothing more than personal preference anyway.


I find that most the most common situation where a class component seems simpler is because the component is broken -- e.g. someone took a shortcut and assumed a prop would never change, made assumptions about the comparisons needed in `componentDidUpdate`, or didn't handle race conditions.

Personally I'm at the point were I think hooks have been vetted enough that I'm comfortably recommending functional components in all situations. I teach a short "Intro to React" workshop and at this point I don't even mention class components except for a very brief FYI at the end, and even that is mostly in case developers encounter class components in Stack Overflow.


I mostly agree with this, and I also prefer using functional components whenever possible, but I think there are still situations where the mental model of class components with their lifecycle hooks is a much better fit for a problem, at least for me.

These tend to come up rarely, but it'll be things like super imperative side-effect controlling components that, for instance, hook into non-React libraries (3D graphics libs, or 3rd party vanilla JS widgets, for example) via escape hatches.

In those scenarios, you're very much in imperative mode, as opposed to declarative mode. Functional components and hooks excel at declarative mode, which most web app code is. Class components with their implicit statefulness and lifecycle hooks model however excel at imperative mode, so when you need that, they are for me the better solution.


> I tend to be "behind" on the latest and greatest in my frontend Dev work. Usually picking stuff up 1 or 2 years after the initial hype.

I think this is a really bad strategy. Just as you shouldn't dive head first into some tool/pattern just because it's the hot new thing, you shouldn't ignore technologies just because they haven't "matured" yet. Some of the "latest and greatest" can really boost your productivity and even make your work more enjoyable and entertaining. Also, if you're paying close attention to the "latest and greatest", you, as a smart and seasoned developer will be able to lead your coworkers away from the hype train when you need to (rather than them leading you onto it).

Having a very big toolkit has certainly served me very well as a developer. Be pragmatic and use knowledge to your advantage. This isn't an industry where ignorance of technologies (even if they're bad ones) has many advantages.


Sorry, but I have to disagree here specifically for the js world. The initial versions very often seem to skip the learnings of previous generations of software engineers and re-implement the same functionality and patterns using new jargon.

The effort and time spent in internalising the new jargon to understand examples and tutorials, to me, feels like a waste.

As the frameworks and libraries near version 1 or sometimes even later, they fall back to traditional tried and tested patterns, besides getting rid of obvious bugs.

So yes, like the gp, I look but don't touch until a little later. I hardly see this happening in other languages.


Yes! I’ve replaced so many HOCs... hooks are so much cleaner.


I'd highly recommend people to stay away from Firebase. The querying options are really lacking. You'll likely get much better performance for much cheaper, and easier to develop for with a cheap postgres instance.


It's a case of using the right tool for the right job. It is indeed lacking for complex queries, and those use cases should probably stick with SQL.

I've been surprised over five years of using Firebase how often complex queries weren't necessary, though! I highly recommend using Firebase if you want realtime data synchronization and great client libraries as well as easy auth and some nice integrations with cloud functions and the like.


I don't mind using SQL (and I would actually prefer it) but what I want to avoid is having to build an api middleware with auth for my personal projects. Are there any alternatives to firebase you would recommend that would allow me to use SQL without having to build out an API?


I was in the exact same position as you one year ago. Then I found Hasura (https://hasura.io) and built Nhost (https://nhost.io). While building Nhost I always had Google Firebase in mind regarding how good they are for the developer experience.


I went through the exercise of replaceing our Firebase with Postgres last year. In the process I built a middleware abstraction that I am opensourcing now : https://supabase.io

As a bonus it even has real-time functionality


Check out postgraphile, and graphile starter - https://github.com/graphile/starter

Combined with graphql-codegen you can essentially generate react hooks from a Postgres schema. It’s awesome - and all typed if you’re using typescript too


May I ask why? I've always found this to be one of the simplest and least painful parts of any web project. And any 3rd party server has inevitably become a problem when the project grew to the point that we wanted something that they didn't have a solution for.


PostgREST does this fairly well.


I went through this exercise myself. Tried to use Firestore and eventually ended up with a $7/mo postgres instance when I realized that my data storage and usage just did not fit well with it. Especially around sorting and pagination.

That said, bluntly telling people to stay away from Firebase as a whole, isn't really the solution here. There are many products available and they are all quite good. I think that everyone should look at their use cases and make their own call on the matter.

I'm still using the realtime store because I'm also using firebase auth (which is excellent). I can update a timestamp for the user in the realtime store and all my clients automatically get triggered. Firebase hosting and firebase functions are pretty nice as well, with very little vendor lockin.


FWIW it's worked well for us, but our application has the follow characteristics: 1) Our data is relatively small and well-scoped, so we're only querying small amounts of data (maybe 10-20 queries each of <50 records) from any individual client 2) We care a lot about real-time, so we want data manipulation on one client to show up pretty immediately on the other 3) While we'd definitely save money switching to a Postgres instance, we're not spending that much to begin with on Firebase.

I think these play well to Firebase's strength. In a previous life I built an app that sucks in a lot of data exhaust and then visualizes it... IMO Firebase wouldn't have worked well for that.


Or Graphql based backends. Which prevent lock-in like Firebase.

Incidentally, Apollo does for Graphql exactly what this post is all about.


Hasura on Postgres works really well too.


I'm using Apollo Cloud Functions with Firebase Functions. Works great.

https://github.com/apollographql/apollo-server/tree/master/p...


Are you referring to Firebase's Realtime Database (often just called "Firebase" since it was the core feature for so long) or Firebase's Cloud FireStore? FireStore is much better (scales more and has more query support) and covers pretty much the same use-case.


In one of the examples, the author fetches results from Firebase, and then sorts them in the browser. I'm not huge on Firebase, but aren't there methods ([0]) to do this on the database, where it'd be much faster and wouldn't waste client cpu?

If this is the case, then this is a bit of faulty abstraction - your database queries are going to be more than just 'select * from <>'. I'm sure there's a way to accomplish this with react hooks without sacrificing elegance for performance.

[0]: https://firebase.google.com/docs/reference/js/firebase.datab...


You are correct - Firebase can order server-side. I also believe I could integrate it without sacrificing elegance. At some point I'll put out a new version that takes advantage of this.


Looking forward to it :)


Some of this comes down to cost optimization.

I believe Firebase charges per record returned. Having an index and sort query doubles the costs compared to client side sorting on the index.


Firestore is cost per record. Firebase Realtime Database is cost for storage and bandwidth.


But at the same time, what if you want to filter records? Doing it on the Firebase side saves both time and money.



I've been using a lot of this library with Firestore and it's great.


Cool, I would suggest supporting it as a template string processor, that way you can escapee (encodeURIComponent) the key values passed in more easily.

    const value = useDbDatam`/sometype/#{someId}/foo`;


Is this bit of code considered kosher javascript?

{[path]: payload}

I don't think I have seen this before... it looks like a short cut to get a dynamic key. I can't decide whether I like it or hate it. It is new to me, and it seems like typescript won't understand it. You will also have a bad time if path === 'constructor'.


Yes, it creates an object with key as the value of path and value the value of payload. If path=1, payload=2, this call would make the object {‘1’: 2 }


That is what I thought, and if path = ['foo','bar'] and payload = 2, it makes {'foo,bar',2}.

It is for sure making max use of dynamic programming. Typescript accepts it as {[path as any]: payload} which is pulling ejection lever on typescript.

Glad I learned something new from this.


It's just a nice quality of life improvement compared to

  const obj = {};
  obj[foo] = 10;


Looks good! I’m going to try it out on a project. Do you have any ideas for hook designs to write/update firebase data?


We don't use hooks for doing writes / updates... I'm curious if there's a clever way to do that. Maybe the useDbData hook could also return a write callback?


I think you have a typo in the second code example:

  let students = useDbDatum(`classes/${classUid}/students`);
  let uids = Object.keys(students || {});
  let paths = studentIds.map(id => `students/${id}/name`);
studentIds on line 3 should probably be uids


Yup... fixed!


There is also Google's own library for that: https://github.com/FirebaseExtended/reactfire


Does someone know an equivalent for Firestore?


React Firebase Hooks (mentioned elsewhere in the thread) works great with Firestore: https://www.npmjs.com/package/react-firebase-hooks




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: