heroku/react-refetch: declarative data fetching for stateless React components
A simple, declarative, and composable way to fetch data for React components
At a glance
- What is it?
- React Refetch maps props to URLs and hands the result back as a PromiseState, so a component never stores fetched data in its own state. It suits read-heavy React views and is a poor fit for apps that already run a Redux store or a query cache.
- Who is it for?
- Adopt React Refetch when your components mostly read data and you want the fetch described next to the component instead of in a reducer. Skip it if you already depend on a query cache with background refetching and cache invalidation, or if you need Suspense-driven loading.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 121 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 30, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The problem React Refetch removes: fetching data without a store
The README frames the project against two patterns it dislikes. Fetching inside a component and dumping the response into local state, the approach React's own initial-ajax tip describes, makes a component "smarter and more mutable than they need to be". Routing every request through actions and a reducer, as Redux or Flux does, is described as over-complicating the architecture when the application is mostly fetching and rendering read-only data: you fetch in an action, reduce into the store, then select the value back out again.
React Refetch targets the second half of that trade-off. It is for React applications whose components are largely consumers of server data, where the value of a global store is low and the cost of wiring one up is high. The README states the project was inspired by, and forked from, React Redux, and that it keeps the connect() decorator shape while changing what is mapped: props to URLs to props, rather than state to props. If your app needs complicated client-side state, the README says so directly, Redux and Flux remain the right pattern.
How connect() maps props to requests and back to PromiseState props
You wrap a component in connect() and pass a function from props to a request description. In the README example, a Profile component with a userId prop is wrapped so that userFetch maps to `/users/${props.userId}` and likesFetch maps to `/users/${props.userId}/likes`. When the component mounts, those requests are calculated, fetched, and the results arrive as props with the names you chose.
Each result is a PromiseState, described in the README as a synchronous representation of the fetch Promise. It is pending, fulfilled or rejected at the moment the component renders, which is what lets render() branch on it without an effect or a subscription. The README's own render example checks `userFetch.pending` first, then `userFetch.rejected` with `userFetch.reason`, then `userFetch.fulfilled` with `userFetch.value`.
Refetching is driven by prop changes. When new props arrive the requests are recalculated, and if they changed, the data is refetched and new PromiseState props are injected. By default requests are compared by URL, headers and body. A request written as an object instead of a plain string can carry a `comparison` attribute, which the README uses to tie `/users/stats` to `props.status` and `props.page` even though neither appears in that URL. The README adds a caveat worth repeating: in general you should rely on changes to the requests themselves, and treat `comparison` as finer-grained control for the cases where it is needed.
Installing react-refetch and a first fetch from a real URL
The README gives one install command and states the React requirement as React 0.14 or later. It assumes npm plus a module bundler such as Webpack or Browserify, because the package is consumed as CommonJS modules.
npm install --save react-refetchThe package entry point is `./lib/index.js` with types at `./lib/index.d.ts`, and `npm run prepare` runs clean, lint and build, so the published `lib` directory is generated by Babel from `src`.
The README also lists four ES6 features the library requires: `Object.assign`, `Promise`, `fetch` and `Array.prototype.find`. It points at compatibility tables for each and says to include polyfills as necessary. That is a real deployment constraint, not a footnote, because `fetch` is absent in older browsers and in Node versions predating it.
A first use, following the README example, is to wrap a component and branch on the PromiseState inside render:
import React, { Component } from 'react'
import { connect } from 'react-refetch'
class Profile extends Component {
render() {
const { userFetch } = this.props
if (userFetch.pending) return <LoadingAnimation/>
if (userFetch.rejected) return <Error error={userFetch.reason}/>
if (userFetch.fulfilled) return <User user={userFetch.value}/>
}
}
export default connect(props => ({
userFetch: `/users/${props.userId}`
}))(Profile)On mount you should see the pending branch, then either the user or the error, with no local state written anywhere in Profile. The README notes that a PromiseStateContainer is not part of the library, because its defaults are application-specific, and links to a gist for one.
Where React Refetch is the wrong tool
The comparison rule is the sharpest limitation. Requests are compared by URL, headers and body, so a response that changes while the request stays identical will not be refetched by a prop change. The `comparison` attribute is the documented workaround, and the README itself hedges it, calling it helpful for finer-grained control rather than the normal path. If your data changes on the server without a corresponding prop change, this library will not notice on its own.
The second limitation is architectural. React Refetch has no store, no cache invalidation and no mutation layer beyond the advanced options the README mentions for lazy loading, polling and posting data to the server. That is the point of the design, but it means two components requesting the same URL each hold their own PromiseState. There is no shared cache to deduplicate them.
The third is maintenance signal. The most recent release listed is v5.0.0-0, dated 2024-05-22, and it is a pre-release version. The release before it, v4.0.1-0, is dated 2020-01-20. The repository's last push was on 2026-06-02 and it is not archived, so the code is not abandoned, but the README still documents the v4 API and does not describe what changed in v5. Anyone installing today should read CHANGELOG.md before assuming the README matches the published package.
Finally, this is a class-component-era API. The README's examples use class components, the `connect()` decorator and the `PromiseState` object. There is no Suspense integration and no hook equivalent described in the README.
React Refetch compared with TanStack Query and RTK Query
The alternatives people search for alongside this project are TanStack Query (formerly React Query) and RTK Query, and the difference is where state lives.
TanStack Query keeps a query cache outside your components. A query is keyed, cached, shared between components that use the same key, and refetched according to stale-time and refetch-interval settings. React Refetch has no such cache: the request lives in the connect() mapping, and the PromiseState lives on the component instance. Two components fetching the same URL do the work twice. In exchange, there is nothing to configure and nothing global to reason about, and the data flow stays visible in the props-to-URL function.
RTK Query sits inside Redux Toolkit and writes fetched data into the Redux store, which is the architecture React Refetch was written to avoid. If you already run Redux, RTK Query adds no new mental model. If you do not, React Refetch asks you to skip the store entirely, which is the README's stated reason for the project existing.
The honest summary: TanStack Query and RTK Query are caches with fetching attached, and React Refetch is fetching with no cache. Choose based on whether sharing and invalidating cached responses is part of your problem.
Licence, upgrade cost and what to check before you depend on it
The repository's package.json declares `"license": "MIT"` and its `files` field publishes only `lib`, so the npm package ships the compiled output of `src` rather than the source tree. The GitHub metadata for the repository reports the licence as NOASSERTION, which means GitHub could not match the file to a known licence template. LICENSE.md is present at the top level. If the MIT declaration in package.json matters to your compliance process, have someone read LICENSE.md and confirm it, since the two signals disagree. Nothing here is legal advice.
Upgrade cost is the practical question. The published version is 5.0.0-0, a pre-release, and the README documents the v4 API. The build is Babel-based: `npm run build` compiles `src` to `lib` and copies the `.d.ts` files, and `npm run prepare` chains clean, lint and build. TypeScript consumers get declarations at `./lib/index.d.ts` and there is an `examples/ts/` directory in the repository. Tests run through mocha with `@babel/register` and a setup file, and coverage through nyc.
The four required globals are the upgrade risk most likely to bite. If you move to a runtime that lacks `fetch`, or you drop a polyfill that was quietly supplying `Array.prototype.find`, the library breaks at the call site, not at import time.
Editorial conclusion
Adopt React Refetch when your components mostly read data and you want the fetch described next to the component instead of in a reducer. Skip it if you already depend on a query cache with background refetching and cache invalidation, or if you need Suspense-driven loading. Before committing, check that your target browsers and Node version provide Object.assign, Promise, fetch and Array.prototype.find, and read the v5.0.0-0 entry in CHANGELOG.md because the README documents the v4 API surface.
Frequently asked questions
How do I install react-refetch?
The README gives a single command, npm install --save react-refetch, and assumes npm with a module bundler such as Webpack or Browserify. It requires React 0.14 or later.
Does react-refetch cache responses or share them between components?
No. The README describes requests calculated from props and returned as PromiseState props on the component, with no store or cache layer, so two components requesting the same URL each hold their own result.
Why does a react-refetch request not refetch when my data changes?
Requests are compared by URL, headers and body by default, so a response that changes while the request stays the same is not refetched. The README documents a comparison attribute on the request object for cases where a prop change should trigger a refetch even though the prop is not in the URL.
Which browsers and runtimes does react-refetch need?
The README lists four required ES6 features: Object.assign, Promise, fetch and Array.prototype.find. It links compatibility tables for each and says to include polyfills as necessary.
Is react-refetch still maintained?
The repository is not archived and its last push was on 2026-06-02. The most recent release listed is v5.0.0-0 from 2024-05-22, a pre-release, while the README still documents the v4 API.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/heroku-react-refetch)