Skip to content

Commit

Permalink
Use flow-copy-source to generate .flow files.
Browse files Browse the repository at this point in the history
  • Loading branch information
StevenXL committed Apr 8, 2022
1 parent c14a7a9 commit d801d9f
Show file tree
Hide file tree
Showing 4 changed files with 126 additions and 3 deletions.
7 changes: 7 additions & 0 deletions dist/index.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export {
unCallbackFn,
unsafeMkCallbackFn,
useExtraDeps,
idExtraDep,
isEqualExtraDep,
} from "./use-extra-deps";
98 changes: 98 additions & 0 deletions dist/use-extra-deps/index.js.flow
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// @flow

import * as React from "react";
import pickBy from "lodash/pickBy";
import omitBy from "lodash/omitBy";
import isFunction from "lodash/isFunction";
import mapValues from "lodash/mapValues";
import values from "lodash/values";
import isEqual from "lodash/isEqual";

export type PrimitiveLangDep = boolean | string | number | null | void | symbol;

// Dependencies that are safe to use in the normal `useEffect` deps array
//
// `PrimitiveDep` is a generic type. Typically usage is to bind the type
// variable `PrimitiveDomainDep` to opaque types that wrap primitives.
export type PrimitiveDep<PrimitiveDomainDep> =
| PrimitiveLangDep
| PrimitiveDomainDep;

// Wrapper around a function that has been wrapped in `useSafeCallback`. This type is here to avoid
// cyclical dependencies.
export opaque type CallbackFn<F> = F;

export const unCallbackFn = <F>(fn: CallbackFn<F>): F => fn;

// Used only by `useSafeCallback`
export function unsafeMkCallbackFn<F: (...Array<any>) => any>(
f: F
): CallbackFn<F> {
return f;
}

export type ExtraDeps<V> =
| {| value: V, comparator: (a: V, b: V) => boolean |}
| CallbackFn<V>;

// Hook used to help avoid pitfalls surrounding misuse of objects and arrays in the deps of
// `useEffect` et. al.
//
// By only allowing `PrimitiveDep`s in the `deps` array and forcing functions and non-primitives
// through `extraDeps`, we can ensure that we are not doing naive reference equality like React
// does for the `deps` array.
//
// See `useSafeEffect` for usage of this hook
//
// Returns an object based upon deps and extraDeps:
// { allDeps: An array that is suitable to use as a deps array for things like `useEffect`
// , extraDepValues: An object that has the same keys as extraDeps but contains their plain values
// }
//
export function useExtraDeps<S: { [key: string]: any }, PrimitiveDomainDep>(
deps: $ReadOnlyArray<PrimitiveDep<PrimitiveDomainDep>>,
extraDeps: S
): {|
allDeps: $ReadOnlyArray<any>,
extraDepValues: $ObjMap<S, <V>(ExtraDeps<V>) => V>,
|} {
const [run, setRun] = React.useState<symbol>(Symbol());
const nonFnsRef = React.useRef(null);

const fns = pickBy(extraDeps, isFunction);
const nonFns = omitBy(extraDeps, isFunction);

const hasChange = () => {
if (nonFnsRef.current === null || nonFnsRef.current === undefined) {
return true;
}
for (const key in nonFns) {
if (
!nonFns[key].comparator(nonFns[key].value, nonFnsRef.current[key].value)
) {
return true;
}
}
return false;
};

if (hasChange()) {
setRun(Symbol());
nonFnsRef.current = nonFns;
}

return {
allDeps: [...deps, ...values(fns), run],
extraDepValues: { ...mapValues(nonFns, ({ value }) => value), ...fns },
};
}

export const idExtraDep = <V: { id: string }>(value: V): ExtraDeps<V> => ({
value,
comparator: (a, b) => a.id === b.id,
});

export const isEqualExtraDep = <V>(value: V): ExtraDeps<V> => ({
value,
comparator: (a: V, b: V): boolean => isEqual(a, b),
});
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"dev": "watch 'yarn run build' src",
"test": "jest",
"test:watch": "yarn run test -- --watch",
"check-git-clean": "./check-git-clean.sh"
"check-git-clean": "./check-git-clean.sh",
"gen-flow": "yarn run flow-copy-source --ignore '**/*.test.js' src dist"
},
"babel": {
"presets": [
Expand Down Expand Up @@ -38,6 +39,7 @@
"@babel/preset-flow": "^7.16.7",
"@babel/preset-react": "^7.16.7",
"flow-bin": "^0.175.1",
"flow-copy-source": "^2.0.9",
"flow-typed": "^3.7.0",
"jest": "^27.5.1",
"watch": "^1.0.2"
Expand Down
20 changes: 18 additions & 2 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1805,7 +1805,7 @@ charenc@0.0.2:
resolved "https://registry.yarnpkg.com/charenc/-/charenc-0.0.2.tgz#c0a1d2f3a7092e03774bfa83f14c0fc5790a8667"
integrity sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=

chokidar@^3.4.0:
chokidar@^3.0.0, chokidar@^3.4.0:
version "3.5.3"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd"
integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==
Expand Down Expand Up @@ -2212,6 +2212,17 @@ flow-bin@^0.175.1:
resolved "https://registry.yarnpkg.com/flow-bin/-/flow-bin-0.175.1.tgz#72237070ba4f293f9e04113481e18929c1de50df"
integrity sha512-zMCP0BPa9BrfBSR7QTcyT/XBwzUbyLdNG0eXvBuNxfHCbMRkUzSceRoOaEZIw+R+GH0UHjVfUvPJ30hXxz1Nfw==

flow-copy-source@^2.0.9:
version "2.0.9"
resolved "https://registry.yarnpkg.com/flow-copy-source/-/flow-copy-source-2.0.9.tgz#0c94ad842f2ae544d5a6b8ae720cee0b8678d742"
integrity sha512-7zX/oHSIHe8YRGiA9QIcC4SW6KF667ikdmiDfbST15up1Ona8dn7Xy0PmSrfw6ceBWDww8sRKlCLKsztStpYkQ==
dependencies:
chokidar "^3.0.0"
fs-extra "^8.1.0"
glob "^7.0.0"
kefir "^3.7.3"
yargs "^15.0.1"

flow-typed@^3.7.0:
version "3.7.0"
resolved "https://registry.yarnpkg.com/flow-typed/-/flow-typed-3.7.0.tgz#c3e087cb39de1a3ba303f5c646daca74c9fa8a21"
Expand Down Expand Up @@ -3083,6 +3094,11 @@ jsonfile@^4.0.0:
optionalDependencies:
graceful-fs "^4.1.6"

kefir@^3.7.3:
version "3.8.8"
resolved "https://registry.yarnpkg.com/kefir/-/kefir-3.8.8.tgz#235932ddfbed422acebf5d7cba503035e9ea05c5"
integrity sha512-xWga7QCZsR2Wjy2vNL3Kq/irT+IwxwItEWycRRlT5yhqHZK2fmEhziP+LzcJBWSTAMranGKtGTQ6lFpyJS3+jA==

keyv@^4.0.0:
version "4.2.2"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.2.2.tgz#4b6f602c0228ef4d8214c03c520bef469ed6b768"
Expand Down Expand Up @@ -4201,7 +4217,7 @@ yargs-parser@^20.2.2:
resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee"
integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==

yargs@^15.1.0:
yargs@^15.0.1, yargs@^15.1.0:
version "15.4.1"
resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8"
integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==
Expand Down

0 comments on commit d801d9f

Please sign in to comment.