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

react-context-fetcher

v2.0.10

Published

Factory to build provider and consumers to fetch data in React

Downloads

20

Readme

React Context Fetcher

npm CircleCI Dependabot Status codecov Commitizen friendly

Simple and universal data fetching library for React using context to consume data. It supports server side rendering (SSR).

$ npm install --save react-context-fetcher
# or
$ yarn add react-context-fetcher

API

import React from 'react';
import { createDataFetcher } from 'react-data-fetcher';

// function fetching data
const getData = async () => fetch(/* ... */).then(res => res.json());

// use the factory to create your fetcher
const fetcher = createDataFetcher(getData);

// the fetcher is composed from HOCs and custom hooks
const {
  // HOC working as a data Provider
  withDataFetcher,
  // HOC working as a data consumer
  withData,
  // custom hook working as a data consumer
  useData,
} = fetcher;

const MyComponent = ({ loading, error, data }) => {
  if (loading) {
    return <p>currently fetching data...</p>;
  }

  if (error) {
    return <p>ups something happen: {error}</p>;
  }

  return <p>got data: {data}</p>
};

export default withDataFetcher(MyComponent);

createDataFetcher(fetcher, options)

Factory to build a fetcher object that includes two HOCs and one custom hook (cf. the previous code sample). The factory may take options.

// factory options
{
   // fetcher name
   name: 'data',
   // we may provide options for the providers
   providerOptions: null,
   // we may provide options for the consumers
   consumerOptions: null,
}

The fetcher's name is used when naming the HOCs & hook. If we were to give book to this option, the resulting object would be withBook, withBookFetcher and useBook. The fetcher option is the function that will be called whenever we want to fetch data.

const getData = (variables, props) => { /* ... */ };

It will receive both the computed variables and received props as arguments.

withDataFetcher(options | wrappedComponent)

It fetches data and manage their lifecycle, the whole state is given through props to children but also dispatched through a react context.

// provider options
{
  // variables (function or object)
  variables: null,
  // pure option
  pure: true,
  // should we refetch on props change
  refetchOnPropChanges: false,
  // function defining if there's a change on props
  // default function comes from https://www.npmjs.com/package/shallowequal
  shouldUpdate: shallowequal,
  // we may want to process the fetched data
  cleanData: null,
}

You may omit options to use this HOC right away on your component (ex: withDataFetcher(Component)), or you may provide the options first and retrieve the configured HOC to apply on your component (ex: withDataFetcher(options)(Component)).

export default compose(
  withDataFetcher({
    variables: { x: 42 },
  }),
  /* ... other HOCs */
)(MyComponent);

The option variables may be an function that will receive props as its first argument.

withDataFetcher({
  variables: (props) => { /* ... */ },
})

The wrapped component will receive 3 props : loading, error and data.

withData(options | wrappedComponent)

withData is a very simple HOC that consumes the context provided by withDataFetcher and sends it to props. There's a few options for this HOC.

// consumer options
{
  // pure option
  pure: true,
}

Like withDataFetcher you may omit those options.

// with options
export default withData({ pure: false })(MyComponent);

// without options
export default withData(MyComponent);

useData()

useData is a custom hook you can use to consume data in a functional component.

const MyComponent = () => {
  const { loading, error, data } = useData();
  
  /* ... */
};

Server Side Rendering

React Context Fetcher comes in with SSR support.

Server side

import React from 'react';
import { renderToString, renderToStaticMarkup } from 'react-dom/server';
import { renderWithData } from 'react-data-fetcher';

const Html = ({ children, data }) => (
    <html>
      <body>
        <div id="root" dangerouslySetInnerHTML={{ __html: children }} />
        <script dangerouslySetInnerHTML={{ __html: `window.__FETCHER_STATE__=${JSON.stringify(data)};` }} />
      </body>
    </html>
);

router.get('*', async (req, res, next) => {
  try {
    const [innerHtml, data] = await renderWithData(<App/>, renderToString);
    const html = renderToStaticMarkup(<Html data={data}>{innerHtml}</Html>)
    
    res.status(200);
    res.send(`<!doctype html>\n${html}`);
    res.end();
  } catch(error) {
    next(error);
  }
});

Client side

import React from 'react';
import { render } from 'react-dom';
import { SSRProvider } from 'react-data-fetcher';

const root = document.getElementById('root');

const tree = (
  <SSRProvider state={window.__FETCHER_STATE__}>
    <App />
  </SSRProvider>
);

render(tree, root);