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-fetcherimport 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);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.
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 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 is a custom hook you can use to consume data in a functional component.
const MyComponent = () => {
const { loading, error, data } = useData();
/* ... */
};React Context Fetcher comes in with SSR support.
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);
}
});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);