├── .gitignore
├── tsconfig.json
├── package.json
├── README.md
├── src
├── index.tsx
└── ReactFastPrefetch.tsx
├── index.js.map
├── index.js
└── yarn.lock
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "esnext",
4 | "module": "es2015",
5 | "removeComments": true,
6 | "sourceMap": true,
7 | "jsx": "react",
8 | "lib": ["es5", "es2015", "dom", "scripthost"],
9 | "moduleResolution": "node",
10 | "outDir": "./"
11 | },
12 | "files": ["src/index.tsx"],
13 | "esModuleInterop": true
14 | }
15 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-fast-prefetch",
3 | "version": "4.0.0",
4 | "description": "Begin fetching data before your react component renders",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "npm test",
8 | "build": "tsc --jsx react"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "git+https://github.com/leedauphinee/react-fast-prefetch.git"
13 | },
14 | "author": "https://github.com/leedauphinee",
15 | "license": "ISC",
16 | "bugs": {
17 | "url": "https://github.com/leedauphinee/react-prefetch/issues"
18 | },
19 | "homepage": "https://github.com/leedauphinee/react-prefetch#readme",
20 | "dependencies": {
21 | "axios": "0.19.2"
22 | },
23 | "devDependencies": {
24 | "@types/react": "^16.9.35",
25 | "@types/react-dom": "^16.9.8",
26 | "typescript": "^3.9.3"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # react-fast-prefetch
2 |
3 | Start prefetching data in your react apps before your components renders.
4 |
5 | ```
6 | yarn add react-fast-prefetch
7 | ```
8 |
9 | Example using redux: https://codesandbox.io/s/react-fast-prefetch-redux-f8f7n
10 |
11 | Example VS not using it: https://codesandbox.io/s/smart-fetch-skz09
12 |
13 | ## How to use it
14 |
15 | Export the ReactPrefetchProvider and wrap your app in it. This allows us to use the useReactPrefetch from anywhere on our site.
16 |
17 | ```javascript
18 | import { ReactPrefetchProvider } from "react-fast-prefetch";
19 |
20 |
21 |
22 | ;
23 | ```
24 |
25 | Import the useReactPrefetch hook into a component where your href link is located.
26 | Destructure the prefetch function from the hook, and call it onMouseEnter or onMouseDown depending on the priorty of your link. Applying to many onMouseEnter prefetches could cause memory issues, so it's recommended to only use onMouseEnter on very high traffic links.
27 |
28 | ```javascript
29 | import { useReactPrefetch } from "react-fast-prefetch";
30 |
31 | const Home = () => {
32 | const { prefetch } = useReactPrefetch();
33 |
34 | const prefetchData = () => {
35 | prefetch("https://jsonplaceholder.typicode.com/todos/1");
36 | };
37 |
38 | return ;
39 | };
40 | ```
41 |
42 | In your component that that needs data, destructure fetchData from the hook, and use it like you would with axios.
43 |
44 | ```javascript
45 | import { useReactPrefetch } from "react-fast-prefetch"
46 |
47 | const About = () => {
48 | const { fetchData } = useReactPrefetch()
49 |
50 | useEffect(() => {
51 | fetchData('https://jsonplaceholder.typicode.com/todos/1').then(response =>
52 | // USE THE RESPONSE FROM FETCH HERE
53 | );
54 | }, [])
55 |
56 | return (
57 |
58 | )
59 |
60 | }
61 | ```
62 |
--------------------------------------------------------------------------------
/src/index.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import axios from "axios";
3 |
4 | const ReactPrefetchContext = React.createContext([]);
5 |
6 | export const ReactPrefetchProvider = ({ children }) => {
7 | const PromiseRef = React.useRef([]);
8 |
9 | const prefetch = (url: string, options = {}) => {
10 | const newData = PromiseRef.current.find((data) => data.url === url);
11 |
12 | if (newData) {
13 | return;
14 | }
15 |
16 | const promise = axios.get(url, options);
17 |
18 | const data = [...PromiseRef.current, { url, value: promise }];
19 | PromiseRef.current = data;
20 | };
21 |
22 | const fetchData = (url, options = {}) => {
23 | const test1 = PromiseRef.current.find((data) => data.url === url);
24 |
25 | if (test1) {
26 | if (test1.value instanceof Promise) {
27 | return test1.value;
28 | }
29 | }
30 | return new Promise((resolve, reject) => {
31 | const newData = PromiseRef.current.find((data) => data.url === url);
32 | if (newData) {
33 | resolve(newData.value);
34 |
35 | const data = PromiseRef.current.filter((d) => d.url !== url);
36 |
37 | PromiseRef.current = data;
38 | } else {
39 | axios
40 | .get(url, options)
41 | .then((res) => {
42 | resolve(res);
43 | })
44 | .catch((err) => {
45 | reject(err);
46 | });
47 | }
48 | });
49 | };
50 |
51 | const data = [PromiseRef.current, prefetch, fetchData];
52 |
53 | return (
54 |
55 | {children}
56 |
57 | );
58 | };
59 |
60 | export const useReactPrefetch = () => {
61 | const context = React.useContext(ReactPrefetchContext);
62 | if (context === undefined) {
63 | throw new Error(
64 | "useReactPrefetch can only be used inside ReactPrefetchProvider"
65 | );
66 | }
67 | const [PromiseRef, prefetch, fetchData] = context;
68 |
69 | React.useEffect(() => {
70 | return () => {
71 | return (PromiseRef.current = []);
72 | };
73 | }, []);
74 |
75 | return { prefetch, fetchData };
76 | };
77 |
--------------------------------------------------------------------------------
/src/ReactFastPrefetch.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import axios from "axios";
3 |
4 | const ReactPrefetchContext = React.createContext([]);
5 |
6 | export const ReactPrefetchProvider = ({ children }) => {
7 | const PromiseRef = React.useRef([]);
8 |
9 | const prefetch = (url: string, options = {}) => {
10 | const newData = PromiseRef.current.find((data) => data.url === url);
11 |
12 | if (newData) {
13 | return;
14 | }
15 |
16 | const promise = axios.get(url, options);
17 |
18 | const data = [...PromiseRef.current, { url, value: promise }];
19 | PromiseRef.current = data;
20 | };
21 |
22 | const fetchData = (url, options = {}) => {
23 | const test1 = PromiseRef.current.find((data) => data.url === url);
24 |
25 | if (test1) {
26 | if (test1.value instanceof Promise) {
27 | return test1.value;
28 | }
29 | }
30 | return new Promise((resolve, reject) => {
31 | const newData = PromiseRef.current.find((data) => data.url === url);
32 | if (newData) {
33 | resolve(newData.value);
34 |
35 | const data = PromiseRef.current.filter((d) => d.url !== url);
36 |
37 | PromiseRef.current = data;
38 | } else {
39 | axios
40 | .get(url, options)
41 | .then((res) => {
42 | resolve(res);
43 | })
44 | .catch((err) => {
45 | reject(err);
46 | });
47 | }
48 | });
49 | };
50 |
51 | const data = [PromiseRef.current, prefetch, fetchData];
52 |
53 | return (
54 |
55 | {children}
56 |
57 | );
58 | };
59 |
60 | export const useReactPrefetch = () => {
61 | const ReactPrefetchContext = React.createContext([]);
62 | const context = React.useContext(ReactPrefetchContext);
63 | if (context === undefined) {
64 | throw new Error(
65 | "useReactPrefetch can only be used inside ReactPrefetchProvider"
66 | );
67 | }
68 | const [PromiseRef, prefetch, fetchData] = context;
69 |
70 | React.useEffect(() => {
71 | return () => {
72 | return (PromiseRef.current = []);
73 | };
74 | }, []);
75 |
76 | return { prefetch, fetchData };
77 | };
78 |
--------------------------------------------------------------------------------
/index.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"file":"index.js","sourceRoot":"","sources":["src/index.tsx"],"names":[],"mappings":"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"}
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | import * as React from "react";
2 | import axios from "axios";
3 | const ReactPrefetchContext = React.createContext([]);
4 | export const ReactPrefetchProvider = ({ children }) => {
5 | const PromiseRef = React.useRef([]);
6 | const prefetch = (url, options = {}) => {
7 | const newData = PromiseRef.current.find((data) => data.url === url);
8 | if (newData) {
9 | return;
10 | }
11 | const promise = axios.get(url, options);
12 | const data = [...PromiseRef.current, { url, value: promise }];
13 | PromiseRef.current = data;
14 | };
15 | const fetchData = (url, options = {}) => {
16 | const test1 = PromiseRef.current.find((data) => data.url === url);
17 | if (test1) {
18 | if (test1.value instanceof Promise) {
19 | return test1.value;
20 | }
21 | }
22 | return new Promise((resolve, reject) => {
23 | const newData = PromiseRef.current.find((data) => data.url === url);
24 | if (newData) {
25 | resolve(newData.value);
26 | const data = PromiseRef.current.filter((d) => d.url !== url);
27 | PromiseRef.current = data;
28 | }
29 | else {
30 | axios
31 | .get(url, options)
32 | .then((res) => {
33 | resolve(res);
34 | })
35 | .catch((err) => {
36 | reject(err);
37 | });
38 | }
39 | });
40 | };
41 | const data = [PromiseRef.current, prefetch, fetchData];
42 | return (React.createElement(ReactPrefetchContext.Provider, { value: data }, children));
43 | };
44 | export const useReactPrefetch = () => {
45 | const context = React.useContext(ReactPrefetchContext);
46 | if (context === undefined) {
47 | throw new Error("useReactPrefetch can only be used inside ReactPrefetchProvider");
48 | }
49 | const [PromiseRef, prefetch, fetchData] = context;
50 | React.useEffect(() => {
51 | return () => {
52 | return (PromiseRef.current = []);
53 | };
54 | }, []);
55 | return { prefetch, fetchData };
56 | };
57 | //# sourceMappingURL=index.js.map
--------------------------------------------------------------------------------
/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@types/prop-types@*":
6 | version "15.7.3"
7 | resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.3.tgz#2ab0d5da2e5815f94b0b9d4b95d1e5f243ab2ca7"
8 | integrity sha512-KfRL3PuHmqQLOG+2tGpRO26Ctg+Cq1E01D2DMriKEATHgWLfeNDmq9e29Q9WIky0dQ3NPkd1mzYH8Lm936Z9qw==
9 |
10 | "@types/react-dom@^16.9.8":
11 | version "16.9.8"
12 | resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-16.9.8.tgz#fe4c1e11dfc67155733dfa6aa65108b4971cb423"
13 | integrity sha512-ykkPQ+5nFknnlU6lDd947WbQ6TE3NNzbQAkInC2EKY1qeYdTKp7onFusmYZb+ityzx2YviqT6BXSu+LyWWJwcA==
14 | dependencies:
15 | "@types/react" "*"
16 |
17 | "@types/react@*", "@types/react@^16.9.35":
18 | version "16.9.35"
19 | resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.35.tgz#a0830d172e8aadd9bd41709ba2281a3124bbd368"
20 | integrity sha512-q0n0SsWcGc8nDqH2GJfWQWUOmZSJhXV64CjVN5SvcNti3TdEaA3AH0D8DwNmMdzjMAC/78tB8nAZIlV8yTz+zQ==
21 | dependencies:
22 | "@types/prop-types" "*"
23 | csstype "^2.2.0"
24 |
25 | axios@0.19.2:
26 | version "0.19.2"
27 | resolved "https://registry.yarnpkg.com/axios/-/axios-0.19.2.tgz#3ea36c5d8818d0d5f8a8a97a6d36b86cdc00cb27"
28 | integrity sha512-fjgm5MvRHLhx+osE2xoekY70AhARk3a6hkN+3Io1jc00jtquGvxYlKlsFUhmUET0V5te6CcZI7lcv2Ym61mjHA==
29 | dependencies:
30 | follow-redirects "1.5.10"
31 |
32 | csstype@^2.2.0:
33 | version "2.6.10"
34 | resolved "https://registry.yarnpkg.com/csstype/-/csstype-2.6.10.tgz#e63af50e66d7c266edb6b32909cfd0aabe03928b"
35 | integrity sha512-D34BqZU4cIlMCY93rZHbrq9pjTAQJ3U8S8rfBqjwHxkGPThWFjzZDQpgMJY0QViLxth6ZKYiwFBo14RdN44U/w==
36 |
37 | debug@=3.1.0:
38 | version "3.1.0"
39 | resolved "https://registry.yarnpkg.com/debug/-/debug-3.1.0.tgz#5bb5a0672628b64149566ba16819e61518c67261"
40 | integrity sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==
41 | dependencies:
42 | ms "2.0.0"
43 |
44 | follow-redirects@1.5.10:
45 | version "1.5.10"
46 | resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a"
47 | integrity sha512-0V5l4Cizzvqt5D44aTXbFZz+FtyXV1vrDN6qrelxtfYQKW0KO0W2T/hkE8xvGa/540LkZlkaUjO4ailYTFtHVQ==
48 | dependencies:
49 | debug "=3.1.0"
50 |
51 | ms@2.0.0:
52 | version "2.0.0"
53 | resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"
54 | integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=
55 |
56 | typescript@^3.9.3:
57 | version "3.9.3"
58 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.3.tgz#d3ac8883a97c26139e42df5e93eeece33d610b8a"
59 | integrity sha512-D/wqnB2xzNFIcoBG9FG8cXRDjiqSTbG2wd8DMZeQyJlP1vfTkIxH4GKveWaEBYySKIg+USu+E+EDIR47SqnaMQ==
60 |
--------------------------------------------------------------------------------