Skip to content

Commit

Permalink
Convert to typescript; Update naming to follow rxfire; Support sub mo…
Browse files Browse the repository at this point in the history
…dules
  • Loading branch information
chrisbianca committed Oct 31, 2018
1 parent e9f1711 commit 6bc7cdc
Show file tree
Hide file tree
Showing 65 changed files with 667 additions and 16,712 deletions.
15 changes: 0 additions & 15 deletions .babelrc.js

This file was deleted.

32 changes: 0 additions & 32 deletions .eslintrc

This file was deleted.

13 changes: 0 additions & 13 deletions .flowconfig

This file was deleted.

8 changes: 4 additions & 4 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
# NPM / Yarn
.rpt2_cache
node_modules
npm-debug.log

# Build output
dist
lib
es
# Rollup build output
**/dist
**/*.d.ts

# OS files
.DS_Store
Expand Down
1 change: 1 addition & 0 deletions auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default as useAuthState, AuthStateHook } from './useAuthState';
6 changes: 6 additions & 0 deletions auth/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "react-firebase-hooks/auth",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"typings": "dist/auth/index.d.ts"
}
25 changes: 25 additions & 0 deletions auth/useAuthState.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { auth, User } from 'firebase';
import { useEffect } from 'react';
import { useDataLoader } from '../util';

export type AuthStateHook = {
user?: firebase.User;
initialising: boolean;
};

export default (auth: auth.Auth): AuthStateHook => {
const { loading, setValue, value } = useDataLoader<User>();

useEffect(() => {
const listener = auth.onAuthStateChanged(setValue);

return () => {
listener();
};
}, []);

return {
initialising: loading,
user: value,
};
};
2 changes: 2 additions & 0 deletions database/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as useList, ListHook } from './useList';
export { default as useObject, ObjectHook } from './useObject';
6 changes: 6 additions & 0 deletions database/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "react-firebase-hooks/database",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"typings": "dist/database/index.d.ts"
}
153 changes: 153 additions & 0 deletions database/useList.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import { database } from 'firebase';
import { useEffect, useState } from 'react';

export type ListHook = {
error?: Object;
list: database.DataSnapshot[];
loading: boolean;
};

type KeyValueState = {
keys: string[];
values: database.DataSnapshot[];
};

export default (query: database.Query): ListHook => {
const [error, setError] = useState(false);
const [loading, setLoading] = useState(true);
// Combine keys and values in a single state hook to allow them to be manipulated together
const [{ values }, setKeysValues] = useState({ keys: [], values: [] });

const onChildAdded = (
snapshot: database.DataSnapshot | null,
previousKey?: string | null
) => {
setKeysValues((prevKeyValueState: KeyValueState) => {
return snapshot
? addChild(prevKeyValueState, snapshot, previousKey)
: prevKeyValueState;
});
};

const onChildChanged = (snapshot: database.DataSnapshot | null) => {
setKeysValues((prevKeyValueState: KeyValueState) => {
if (!snapshot || !snapshot.key) {
return prevKeyValueState;
}

const index = prevKeyValueState.keys.indexOf(snapshot.key);
return {
...prevKeyValueState,
values: [
...prevKeyValueState.values.slice(0, index),
snapshot,
...prevKeyValueState.values.slice(index + 1),
],
};
});
};

const onChildMoved = (
snapshot: database.DataSnapshot | null,
previousKey?: string | null
) => {
setKeysValues((prevKeyValueState: KeyValueState) => {
if (!snapshot) {
return prevKeyValueState;
}
// Remove the child from it's previous location
const tempKeyValueState = removeChild(prevKeyValueState, snapshot);
// Add the child into it's new location
return addChild(tempKeyValueState, snapshot, previousKey);
});
};

const onChildRemoved = (snapshot: database.DataSnapshot | null) => {
setKeysValues((prevKeyValueState: KeyValueState) => {
return snapshot
? removeChild(prevKeyValueState, snapshot)
: prevKeyValueState;
});
};

useEffect(
() => {
// This is here to indicate that all the data has been successfully received
query.once(
'value',
() => {
setLoading(false);
},
(err: object) => {
setError(err);
setLoading(false);
}
);
query.on('child_added', onChildAdded);
query.on('child_changed', onChildChanged);
query.on('child_moved', onChildMoved);
query.on('child_removed', onChildRemoved);

return () => {
query.off('child_added', onChildAdded);
query.off('child_changed', onChildChanged);
query.off('child_moved', onChildMoved);
query.off('child_removed', onChildRemoved);
};
},
// TODO: Check if this works suitably for 'query' parameters
[query]
);

return {
error,
list: values,
loading,
};
};

const addChild = (
keyValueState: KeyValueState,
snapshot: firebase.database.DataSnapshot,
previousKey?: string | null
): KeyValueState => {
if (!snapshot.key) {
return keyValueState;
}

const { keys, values } = keyValueState;
if (!previousKey) {
// The child has been added to the start of the list
return {
keys: [snapshot.key, ...keys],
values: [snapshot, ...values],
};
}
// Establish the index for the previous child in the list
const index = keys.indexOf(previousKey);
// Insert the item after the previous child
return {
keys: [...keys.slice(0, index + 1), snapshot.key, ...keys.slice(index + 1)],
values: [
...values.slice(0, index + 1),
snapshot,
...values.slice(index + 1),
],
};
};

const removeChild = (
keyValueState: KeyValueState,
snapshot: firebase.database.DataSnapshot
): KeyValueState => {
if (!snapshot.key) {
return keyValueState;
}

const { keys, values } = keyValueState;
const index = keys.indexOf(snapshot.key);
return {
keys: [...keys.slice(0, index), ...keys.slice(index + 1)],
values: [...values.slice(0, index), ...values.slice(index + 1)],
};
};
33 changes: 33 additions & 0 deletions database/useObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { database } from 'firebase';
import { useEffect } from 'react';
import { useDataLoader } from '../util';

export type ObjectHook = {
error?: object;
loading: boolean;
value?: database.DataSnapshot;
};

export default (query: database.Query): ObjectHook => {
const { error, loading, setError, setValue, value } = useDataLoader<
database.DataSnapshot
>();

useEffect(
() => {
query.on('value', setValue, setError);

return () => {
query.off('value', setValue);
};
},
// TODO: Check if this works suitably for 'ref' parameters
[query]
);

return {
error,
loading,
value,
};
};
2 changes: 2 additions & 0 deletions firestore/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { default as useCollection, CollectionHook } from './useCollection';
export { default as useDocument, DocumentHook } from './useDocument';
6 changes: 6 additions & 0 deletions firestore/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "react-firebase-hooks/firestore",
"main": "dist/index.cjs.js",
"module": "dist/index.esm.js",
"typings": "dist/firestore/index.d.ts"
}
38 changes: 38 additions & 0 deletions firestore/useCollection.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { firestore } from 'firebase';
import { useEffect } from 'react';
import { useDataLoader } from '../util';

export type CollectionHook = {
error?: object;
loading: boolean;
value?: firestore.QuerySnapshot;
};

export default (
query: firestore.Query,
options?: firestore.SnapshotListenOptions
): CollectionHook => {
const { error, loading, setError, setValue, value } = useDataLoader<
firestore.QuerySnapshot
>();

useEffect(
() => {
const listener = options
? query.onSnapshot(options, setValue, setError)
: query.onSnapshot(setValue, setError);

return () => {
listener();
};
},
// TODO: Check if this works suitably for 'query' parameters
[query]
);

return {
error,
loading,
value,
};
};
38 changes: 38 additions & 0 deletions firestore/useDocument.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { firestore } from 'firebase';
import { useEffect } from 'react';
import { useDataLoader } from '../util';

export type DocumentHook = {
error?: object;
loading: boolean;
value?: firestore.DocumentSnapshot;
};

export default (
ref: firestore.DocumentReference,
options?: firestore.SnapshotListenOptions
): DocumentHook => {
const { error, loading, setError, setValue, value } = useDataLoader<
firestore.DocumentSnapshot
>();

useEffect(
() => {
const listener = options
? ref.onSnapshot(options, setValue, setError)
: ref.onSnapshot(setValue, setError);

return () => {
listener();
};
},
// TODO: Check if this works suitably for 'ref' parameters
[ref]
);

return {
error,
loading,
value,
};
};
Loading

0 comments on commit 6bc7cdc

Please sign in to comment.