New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Reactions + DI & IoC proposal #38
Comments
/***** DI & IoC PROPOSAL *****/
// DIRTY HACK EXAMPLE
const fetchUserDone = declareAction()
const fetchUser = declareAction(
null,
(store, payload) => store.fetch('/user', payload)
.then(response => store.dispatch(fetchUserDone(response)))
)
// implementation
const store = createStore()
store.fetch = process.env.TEST
? (...a) => Promise.resolve(__data__)
: fetch
// BRANDED (TYPE) SAFETY CONTEXTS EXAMPLE
const fetchContext = declareContext()
const fetchUserDone = declareAction()
const fetchUser = declareAction(
null,
fetchContext.handle(
(store, payload, fetch) => fetch('/user', payload)
.then(response => store.dispatch(fetchUserDone(response)))
)
)
const store = withContext(createStore(), [
fetchContext.init(
process.env.TEST ? (...a) => Promise.resolve(__data__) : fetch
)
])
// implementation
function declareContext(
createHandler = (store) => (cb, payload, ctx) => cb(store, payload, ctx)
) {
const id = Symbol()
return {
init: context => ({ id, context, createHandler }),
handle (cb) => (payload, { [id]: meta }) =>
meta && meta.handler(cb, payload, meta.context),
}
}
function withContext(store, contextWorkers) {
contextWorkers.forEach(
({ id, context, createHandler }) => store[id] = { context, handler: createHandler(store) }
)
return store
}
// MAXIMUM SUGAR EXAMPLE
const [fetchUser, fetchUserDone] = declareFetch(payload => ['/user', payload])
// implementation
function declareFetch(cb) {
const responseAction = declareAction('fetch response')
const errorAction = declareAction('fetch error')
const requestAction = declareAction(
'fetch request',
fetchContext.handle(
(store, payload, fetch) => fetch(...cb(payload))
.then(response => store.dispatch(responseAction(response)))
.catch(error => store.dispatch(errorAction(error)))
)
)
return [requestAction, responseAction, errorAction]
} |
const fetchFactory = createFactory();
// declare function createFactory<T>(): <U extends any[], V>(...args: U) => (f: (x: T) => (...args: U) => V) => V;
const helpFactory = createFactory();
store
.attach(fetchFactory, fetch)
.attach(helpFactory, {
url: {
myRequest: id => `user/${id}`
}
});
// or we can use something independent of reatom
const fetchFactory = createFactory('domain');
const helpFactory = createFactory('domain');
attachFactory('domain', fetchFactory, fetch)
attachFactory('domain', helpFactory, {
url: {
myRequest: id => `user/${id}`
}
});
//
const responseAction = declareAction('fetch response')
const errorAction = declareAction('fetch error')
const requestAction = declareAction(
'fetch request',
fetchFactory(fetch =>
helpFactory(({ url }) =>
store => payload => fetch(url.myRequest(payload))
.then(response => store.dispatch(responseAction(response)))
.catch(error => store.dispatch(errorAction(error)))
)
)
); |
Contextimplementation let id = 0;
export const declareContext = (value) => {
const key = ++id;
return {
Provide: override => ({ key, value: override }),
key,
value
}
} usage const Network = declareContext(fetch); override if need pointwise (not initialize!)const store = createStore(RootAtom, {}, [
Network.Provide(fetchForTests) // Override defalut context value in this store
]);
const store = createStore(RootAtom, {}); // Network context should works inside store
// OR as hoc like
// function withContext(store, contextOverrides) {} getContextimplementation inside store // fill data
const _contexts = {};
for(const ctx of contexts) _contexts[ctx.key] = e.value
const getContext = ({ key, value }) => _contexts[key] || value Reactionsusage const fetchPage = declareAction(async (store, payload) => {
// Data from another atom
const sort = store.getState(Sort);
// Use declarated fetch
const res = await store.getContext(Network).get(`/products/${payload}`, { sort });
// Use async normailzer
const data = await store.getContext(Normalizer).normalize(res.data, schema);
// Push data to store
store.dispatch(fetchPageDone(data.result));
})
const fetchPageDone = declareAction()
const ProductsPage = declareAtom({
products: [],
page: 1,
loading: false
}, on => [
on(fetchPage, (state, payload) => { ...state, loading: true, page: payload }),
on(fetchPageDone, (state, payload) => { ..state, loading: false, products: payload }),
]) |
artalar
added a commit
that referenced
this issue
Dec 26, 2019
artalar
added a commit
that referenced
this issue
Jan 16, 2020
artalar
added a commit
that referenced
this issue
Jan 16, 2020
artalar
added a commit
that referenced
this issue
Jan 16, 2020
Merged
artalar
added a commit
that referenced
this issue
Jan 16, 2020
artalar
added a commit
that referenced
this issue
Jan 16, 2020
artalar
added a commit
that referenced
this issue
Jan 16, 2020
artalar
added a commit
that referenced
this issue
Jan 16, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Purposes
Implementation
version 1
version 2
Inside createStore
Example usage
The text was updated successfully, but these errors were encountered: