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 🙏

© 2026 – Pkg Stats / Ryan Hefner

use-pq

v0.0.38

Published

Queryless GraphQL

Downloads

164

Readme

npm npm bundle size Codecov GitHub license

About The Project

usePq aims to make GraphQL consumption truly only-what-you-need. GraphQL is a great tool for data fetching without bombarding an API with chained requests or building a local replica. The one thing that annoys me about GraphQL is writing query files. These need to be tweaked, formatted, and in some cases compiled and shipped as utilities.

Building a query per page seems to me like patching RESTful thinking into GraphQL. The idea behind usePq is to do with query declarations and instead use observables to build the exact query that you need, just as GraphQL was meant to be used.

To view the full documentation, go to use-pq.com.

Package Details

Getting Started

usePq is not invasive: you can use as little or as much as you want. You only need to provide a fetching function and start querying away.

Prerequisites

usePq has a peer dependency on React 17+.

Installation

pnpm add use-pq

Basic Usage

In a component, call usePq and provide a query handler. You can then request fields to fetch by accessing keys from p.

import { usePq } from 'use-pq'
import client from 'api'

export function UserStatus() {
  const [p, q, { isLoading }] = usePq(async (query) =>
    // Use any GraphQL client that can post a string query
    // and set the response.
    client.query(query).then(({ data }) => data)
  )

  // Access and build any reference from p
  const user = p.session.user

  const displayName = `${user.title} ${user.name}`

  return (
    <div>
      {isLoading ? (
        <span>loading...</span>
      ) : (
        <span>
          {displayName}: {user.status}
        </span>
      )}
    </div>
  )
}

API

const [p, q, { isLoading, commitQuery }] = usePq(handler)

Arguments

handler: usePq takes a single argument, which is a function with two arguments: the query and a data setter.

The data setter must be called asynchronously.

Return value

p: A Proxy that captures the values that are needed during the first render phase.

q: The query that was built from the render phase from accessing `` properties. If the field was accessed by React during rendering, it will also be registered.

isLoading: The state of the field capture phase. This is true while a query does not exist and the client has not set any data.

commitQuery: A function that can be called to manually trigger a commit of captured changes to the query.

Feature Usage

Lists of fields

Lists of fields cannot be access by themselves. It is possible to declare a field as a field list by accessing .listOf('fieldName') on the parent.

export function Users() {
  const [p, q, { isLoading }] = usePq(handler)

  // users is a plain array
  const users = p.listOf('users')

  // On the first render, pq will capture the values
  // used by the component by with list having a
  // single proxy entry i.e. list = [proxy]
  return (
    <div>
      {isLoading ? (
        // This will be the first node to be painted
        // to the browser, since pq will trigger a rerender
        // with isLoading = true after capturing
        <span>loading...</span>
      ) : (
        // React will attempt to render name by checking if
        // if it a valid element. When an object is being verified,
        // React checks if it has Symbol.iterator. When the iterator
        // property is accessed, the field is registered for the query.
        users.map(({ name }) => <span>{name}</span>)
      )}
    </div>
  )
}

Fields with arguments

Fields with arguments can be declared by accessing a key in bracket notation.

export function User({ id }) {
  const [p, q, { isLoading }] = usePq(handler)

  // Proxies can destructure properties
  const { id, name } = p[`user(id: ${id})`]

  return (
    <div>
      {isLoading ? (
        <span>loading...</span>
      ) : (
        <span>
          {id}: {name}
        </span>
      )}
    </div>
  )
}

Field lists with arguments

Combining the argument and list notation will return an array.

export function UsersLimit({ limit }) {
  const [p, q, { isLoading }] = usePq(handler)

  const users = p
    .listOf(`users(limit: ${limit})`)
    .map(({ id, name }) => `${id}: ${name}`)

  return (
    <div>
      {isLoading ? (
        <span>loading...</span>
      ) : (
        users.map((entry) => <span>{entry}</span>)
      )}
    </div>
  )
}

Arguments as a function

It is possible to provide arguments without string interpolation by using a $ prefix after the field that needs arguments.

export function User({ id }) {
  const [p, q, { isLoading }] = usePq(handler)

  // The function name can be anything
  // as long as the first character is $
  const { id, name } = p.user.$({ id })

  return (
    <div>
      {isLoading ? (
        <span>loading...</span>
      ) : (
        <span>
          {id}: {name}
        </span>
      )}
    </div>
  )
}

Fields with arguments as functions

Arguments as function can also be used for list fields.

export function Users() {
  const [p, q, { isLoading }] = usePq(handler)

  // The function name can be anything
  // as long as the first character is $
  const users = p
    .listOf('users')
    .$({ limit })
    .map(({ id, name }) => `${id}: ${name}`)

  return (
    <div>
      {isLoading ? (
        <span>loading...</span>
      ) : (
        users.map((entry) => <span>{entry}</span>)
      )}
    </div>
  )
}

Committing captured changes in children

usePq relies on rerendering cycles to capture and commit fields that were accessed. If usePq is call in a parent component and passed down as a prop to a child, rerendering the child and not the parent will not trigger the commit. Invoking commitQuery does this job.

function App() {
  const [{ user }, q, { commitQuery, isLoading }] = usePq(handler)

  return <User user={user} commitQuery={commitQuery} />
}

export function User({ user, commitQuery }) {
  const [id, setId] = useState(1)

  // When id changes, the query will be updated after
  // rendering.
  useEffect(commitQuery, [id])

  return (
    <div>
      {isLoading ? <span>loading...</span> : <span>{user.$({ id }).name}</span>}
      <button onClick={() => setId(i + 1)}>next</button>
    </div>
  )
}

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feat/title)
  3. Commit your Changes (git commit -m 'Add feature')
  4. Push to the Branch (git push origin feat/title)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE.txt for more information.

Contact

Project Link: https://github.com/ofrbg/use-pq