npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

firestore-livehooks

v1.0.1

Published

Hooks to easily subscribe to live-updated Firestore collections in React and React Native

Downloads

1

Readme

firestore-livehooks

This package solves the common design pattern where a React component wants to show a collection from Firestore that live-updates (i.e. that subscribes to Firestore changes and updates the UI).

Installation

npm install firestore-livehooks or yarn add firestore-livehooks. The package assumes you're using React or React Native, and also that you're using some flavor of Firestore (whether the Web SDK or perhaps react-native-firebase).

Usage

Most people will just use the useLiveQueryResult hook. Some might use the reconcileSnapshotChanges utility function directly.

useLiveQueryResult

This hook returns an up-to-date array reflecting the Firestore query you specify. The result will reflect ongoing changes you make that might impact the results of the underlying query. It does this by subscribing to changes on your query and reconciling those changes with an in-memory cache of past data.

function MyReactComponent() {
  const latestTime = 8675309;
  const todoList = useLiveQueryResult(
    useCallback( // more on this below
      () => firebase
        .firestore()
        .collection("todos")
        .where("timestamp", ">=", latestTime),
      [latestTime]
    ),
    getTodoID, // Function that extracts a key from the type of item in your collection
  );
  
  return (
    <View>
      { todoList.map(t => renderTodo(t)) }
    </View>
  );
}

function getTodoID(todo: Todo) {
  return todo.id;
}

The code above will keep todoList up to date with the latest changes, whether you add/remove/update the todos from elsewhere in the code. Note that you should pass callbacks for both parameters of useLiveQueryResult that do not change upon re-renders -- otherwise, the hook will keep thinking you've changed its inputs and keep resubscribing to the collection and causing a rendering loop.

So: do not just pass firestore.firebase().collection("todos") to useLiveQueryResult — if you do, every time MyReactComponent re-renders, useLiveQueryResult will cause yet another re-render because it will think you've changed its inputs. Instead, useCallback or useMemo to keep those changes to a minimum. In the above example, useLiveQueryResult will only change its query subscription when latestTime changes, which is exactly what you want.

reconcileSnapshotChanges

This is a utility function that you might find useful to directly use at times, though most people will just need useLiveQueryResult. reconcileSnapshotChanges takes a snapshot and integrates all its changes into an in-memory Map of existing objects. This saves you the trouble of having to deal with added, removed, and modified change types yourself.

  const myTodos = useRef(new Map());
  
  useEffect(() => {
    function onNewBootlegs(snap: QuerySnapshot) {
      // You want myTodos as a ref, not just as a `new Map()` directly, because
      // you don't want the closure here to capture a version of the map that's
      // different from subsequent renders.
      reconcileSnapshotChanges(snap, myTodos.current, getTodoID);
    }
    
    return firebase.firestore().collections("bootlegs").onSnapshot(onNewBootlegs);
  }, []);
  
  return (
    <View>{/* use myTodos.current somehow */}</View>
  );