-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
133 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
import { useEffect, useState } from "react"; | ||
|
||
const actionListeners = {}; | ||
|
||
const thunkRX = /.*=>.*dispatch.*=>/i; | ||
|
||
const isThunk = (fn) => !!fn.toString().match(thunkRX); | ||
const asArray = (a) => (Array.isArray(a) ? a : [a]); | ||
const asKey = (str) => (typeof str === "function" ? str().toString() : str); | ||
const actionKey = (action) => | ||
typeof action === "function" ? action.toString() : action.type; | ||
|
||
// redux middleware that will call the action listeners | ||
export const actionListener = () => (next) => (action) => { | ||
const key = actionKey(action); | ||
const listeners = actionListeners[key]; | ||
if (listeners) { | ||
listeners.forEach((listener) => listener(action)); | ||
} | ||
return next(action); | ||
}; | ||
|
||
const processListeners = (listeners, eventCallback) => { | ||
listeners.reduce((a, c) => { | ||
if (typeof c === "function" && !isThunk(c)) { | ||
a.forEach((e) => { | ||
const key = asKey(e); | ||
eventCallback(key, c); | ||
}); | ||
return []; | ||
} | ||
return [...a, c]; | ||
}, []); | ||
}; | ||
|
||
// hook for setting listeners on actions | ||
export function useActionListeners(...listeners) { | ||
useEffect(() => { | ||
processListeners(listeners, (event, callback) => { | ||
const eventListeners = actionListeners[event]; | ||
if (eventListeners) { | ||
eventListeners.push(callback); | ||
} else { | ||
actionListeners[event] = [callback]; | ||
} | ||
}); | ||
|
||
return function cleanup() { | ||
processListeners(listeners, (event, callback) => { | ||
const eventListeners = actionListeners[event]; | ||
eventListeners.splice(eventListeners.indexOf(callback), 1); | ||
}); | ||
}; | ||
// eslint-disable-next-line | ||
}, []); | ||
} | ||
|
||
// hook for a standard fetch operation with pending and error states | ||
export function useFetchState({ | ||
fetch, | ||
success, | ||
failure, | ||
failureHandler = (e) => e, | ||
}) { | ||
const [state, setState] = useState({ | ||
pending: false, | ||
error: null, | ||
}); | ||
|
||
useActionListeners( | ||
...asArray(fetch), | ||
() => | ||
setState({ | ||
pending: true, | ||
error: null, | ||
}), | ||
|
||
...asArray(success), | ||
() => | ||
setState({ | ||
pending: false, | ||
error: null, | ||
}), | ||
|
||
...asArray(failure), | ||
(errorAction) => | ||
setState({ | ||
pending: false, | ||
error: failureHandler(errorAction), | ||
}) | ||
); | ||
|
||
return [state.pending, state.error]; | ||
} | ||
|
||
// hook as an experiment | ||
// modifies the thunk and makes it trigger the pending state | ||
export const withPendingState = (thunk) => (...done) => { | ||
const [loading, setLoading] = useState(false); | ||
|
||
useActionListeners(...done, () => setLoading(false)); | ||
|
||
return [ | ||
loading, | ||
(...a) => { | ||
setLoading(true); | ||
return thunk(...a); | ||
}, | ||
]; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{ | ||
"name": "redux-signal", | ||
"version": "0.1.0", | ||
"description": "Simple Action listener library for redux and react", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/jsbuzz/redux-signal.git" | ||
}, | ||
"keywords": [ | ||
"redux", | ||
"react" | ||
], | ||
"author": "Matyas Buczko", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/jsbuzz/redux-signal/issues" | ||
}, | ||
"homepage": "https://github.com/jsbuzz/redux-signal#readme" | ||
} |