Created
July 8, 2019 16:47
-
-
Save crobinson42/b30fe224b8c26e07f3fdac43a35f7342 to your computer and use it in GitHub Desktop.
JS-Data React Hook useStoreQuery(mapperName, query)
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
import React from 'react' | |
import useStoreQuery from './useStoreQuery' | |
const ActiveUsers = ({ storeQuery, storeQueryLoading }) => { | |
const { users, loading } = useStoreQuery('users', { where: { active: true } }) | |
return ( | |
<div>{loading ? 'Loading...' : `${users.length} active users found`}</div> | |
) | |
} | |
export default ActiveUsers |
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
import React, { useEffect, useReducer } from 'react' | |
import axios from 'axios' | |
import models from './models' | |
import deepEqual from 'fast-deep-equal' | |
const httpClient = axios.create({ | |
baseURL: 'http://api.example.com', | |
}) | |
const store = models.browser.configHttp({ httpClient }) | |
function reducer(state, action) { | |
switch (action.type) { | |
case 'set_data': | |
return { ...state, data: action.payload, loading: false }; | |
case 'fetch_data': | |
return { ...state, loading: true, prevQuery: action.payload }; | |
default: | |
return state | |
} | |
} | |
const useStoreQuery = (modelName, query) => { | |
const [state, dispatch] = useReducer(reducer, { data: undefined, loading: true, prevQuery: undefined }) | |
useEffect(() => { | |
const run = async () => { | |
if (dispatch) | |
dispatch({ type: 'fetch_data', payload: query }) | |
let op | |
if (typeof query === 'object') op = 'findAll' | |
else if (typeof query === 'string') op = 'find' | |
else | |
throw new Error( | |
`useStoreQuery model query should return an object or string, ${modelName} received ${typeof query}`, | |
) | |
if (!store[modelName]) | |
throw new Error( | |
`useStoreQuery modelName "${modelName}" not found on store`, | |
) | |
console.log(`useStoreQuery(${modelName}, ${JSON.stringify(query || {})})`) | |
store[modelName][op] | |
.call(store, query) | |
.catch(err => { | |
console.log(`useStoreQuery ${modelName}#${op} err`, err) | |
return op === 'findAll' ? [] : undefined | |
}) | |
.then(result => { | |
if (dispatch) | |
dispatch({ type: 'set_data', payload: result }) | |
}) | |
} | |
if (!deepEqual(query, state.prevQuery) && Boolean(query)) | |
run() | |
}, [modelName, query]) | |
return { | |
[modelName]: state.data, | |
loading: state.loading, | |
} | |
} | |
export default useStoreQuery |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment