diff --git a/CHANGELOG.md b/CHANGELOG.md index 17e9137..4beb124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Fixed ### Removed +## [1.0.0-alpha.2] - 2020-02-29 +### Added +- feat: Catch read errors +- chore: Lint end-to-end tests react-app code + +### Changed +- feat: [BREAKING CHANGE] Pass all component props to provider defined as functions, not only "query" property +- feat: Use useRefresh in "withData", "withError" and "withLoading" + ## [1.0.0-alpha.1] - 2020-02-26 ### Added - feat: First pre-release diff --git a/package-lock.json b/package-lock.json index cbbb0a5..8ec198d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@data-provider/react", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 79d61f2..465455d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@data-provider/react", - "version": "1.0.0-alpha.1", + "version": "1.0.0-alpha.2", "description": "React bindings for @data-provider", "keywords": [ "data-provider", @@ -22,7 +22,7 @@ "main": "dist/index.cjs.js", "module": "dist/index.esm.js", "scripts": { - "lint": "eslint src test test-e2e/cypress", + "lint": "eslint src test test-e2e/cypress test-e2e/react-app/src", "lint-staged": "lint-staged", "build": "rollup --config", "test": "jest", diff --git a/sonar-project.properties b/sonar-project.properties index 45fc9fa..5ff0e1f 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,6 +1,6 @@ sonar.organization=data-provider sonar.projectKey=data-provider-react -sonar.projectVersion=1.0.0-alpha.1 +sonar.projectVersion=1.0.0-alpha.2 sonar.sources=src,test sonar.exclusions=node_modules/** diff --git a/src/useDataProvider.js b/src/useDataProvider.js index b62c400..0cc6af3 100644 --- a/src/useDataProvider.js +++ b/src/useDataProvider.js @@ -3,23 +3,30 @@ import { useSelector } from "react-redux"; export const useRefresh = dataProvider => { useEffect(() => { - dataProvider.read(); - return dataProvider.on("cleanCache", () => { - dataProvider.read(); - }); + if (dataProvider) { + const catchError = err => { + console.error( + `@data-provider/react: Error "${err.message}" in provider "${dataProvider.id}"` + ); + }; + dataProvider.read().catch(catchError); + return dataProvider.on("cleanCache", () => { + dataProvider.read().catch(catchError); + }); + } }, [dataProvider]); }; export const useData = (dataProvider, comparator) => { - return useSelector(() => dataProvider.state.data, comparator); + return useSelector(() => dataProvider && dataProvider.state.data, comparator); }; export const useLoading = (dataProvider, comparator) => { - return useSelector(() => dataProvider.state.loading, comparator); + return useSelector(() => dataProvider && dataProvider.state.loading, comparator); }; export const useError = (dataProvider, comparator) => { - return useSelector(() => dataProvider.state.error, comparator); + return useSelector(() => dataProvider && dataProvider.state.error, comparator); }; export const useDataProvider = (dataProvider, comparator) => { diff --git a/src/withDataProvider.js b/src/withDataProvider.js index c6b3842..5f47333 100644 --- a/src/withDataProvider.js +++ b/src/withDataProvider.js @@ -8,13 +8,13 @@ const isFunction = provider => { const defaultKeys = ["data", "loading", "error"]; -const useProvider = (provider, query) => { +const useProvider = (provider, props) => { return useMemo(() => { if (isFunction(provider)) { - return provider(query); + return provider(props); } return provider; - }, [provider, query]); + }, [provider, props]); }; const getProp = (data, key) => { @@ -58,7 +58,7 @@ export const withDataProviderBranch = (provider, keys) => ( LoadingComponent, ErrorComponent ) => props => { - const providerToRead = useProvider(provider, props.query); + const providerToRead = useProvider(provider, props); const { dataProp, loadingProp, errorProp, loading, error } = useDataProviderCustomProps( providerToRead, keys @@ -79,25 +79,28 @@ export const withDataProviderBranch = (provider, keys) => ( }; export const withDataProvider = (provider, keys) => Component => props => { - const providerToRead = useProvider(provider, props.query); + const providerToRead = useProvider(provider, props); const { dataProp, loadingProp, errorProp } = useDataProviderCustomProps(providerToRead, keys); return ; }; export const withData = (provider, key) => Component => props => { - const providerToRead = useProvider(provider, props.query); + const providerToRead = useProvider(provider, props); + useRefresh(providerToRead); const { dataProp } = useDataCustomProp(providerToRead, key); return ; }; export const withLoading = (provider, key) => Component => props => { - const providerToRead = useProvider(provider, props.query); + const providerToRead = useProvider(provider, props); + useRefresh(providerToRead); const { loadingProp } = useLoadingCustomProp(providerToRead, key); return ; }; export const withError = (provider, key) => Component => props => { - const providerToRead = useProvider(provider, props.query); + const providerToRead = useProvider(provider, props); + useRefresh(providerToRead); const { errorProp } = useErrorCustomProp(providerToRead, key); return ; }; diff --git a/test-e2e/react-app/src/modules/books-search/BooksSearch.js b/test-e2e/react-app/src/modules/books-search/BooksSearch.js index 2e686f0..f7c3d2a 100644 --- a/test-e2e/react-app/src/modules/books-search/BooksSearch.js +++ b/test-e2e/react-app/src/modules/books-search/BooksSearch.js @@ -32,7 +32,7 @@ const BooksSearch = () => { placeholder="Type to search" onChange={handleChange} /> - + ); }; diff --git a/test-e2e/react-app/src/modules/books-search/modules/books-search-results/BooksSearchResults.js b/test-e2e/react-app/src/modules/books-search/modules/books-search-results/BooksSearchResults.js index e74520d..2e104d4 100644 --- a/test-e2e/react-app/src/modules/books-search/modules/books-search-results/BooksSearchResults.js +++ b/test-e2e/react-app/src/modules/books-search/modules/books-search-results/BooksSearchResults.js @@ -1,7 +1,7 @@ import React, { memo } from "react"; import Proptypes from "prop-types"; -import { withData, withLoading, withRefresh } from "@data-provider/react"; +import { withData, withLoading } from "@data-provider/react"; import { booksSearch } from "data/books"; import BooksList from "modules/books-list"; @@ -9,9 +9,9 @@ import ItemsListContainer from "components/items-list-container"; import Loading from "components/loading"; import NoResults from "components/no-results"; -const queryBooks = search => booksSearch.query({ search }); +const queryBooks = ({ search }) => booksSearch.query({ search }); -const ConnectedBooks = withRefresh(queryBooks)(withData(queryBooks, "books")(BooksList)); +const ConnectedBooks = withData(queryBooks, "books")(BooksList); const BooksSearchResults = ({ search, books, loading }) => { console.log("Rendering books search results", loading, books); @@ -21,7 +21,7 @@ const BooksSearchResults = ({ search, books, loading }) => { {loading && } {hasNotResults && } - + ); }; @@ -32,8 +32,8 @@ BooksSearchResults.propTypes = { loading: Proptypes.bool }; -const BooksSearchResultsConnected = withRefresh(queryBooks)( - withLoading(queryBooks)(withData(queryBooks, "books")(BooksSearchResults)) +const BooksSearchResultsConnected = withLoading(queryBooks)( + withData(queryBooks, "books")(BooksSearchResults) ); export default memo(BooksSearchResultsConnected); diff --git a/test-e2e/react-app/src/modules/rerenderer/Rerenderer.js b/test-e2e/react-app/src/modules/rerenderer/Rerenderer.js index 30f8a14..1b4e694 100644 --- a/test-e2e/react-app/src/modules/rerenderer/Rerenderer.js +++ b/test-e2e/react-app/src/modules/rerenderer/Rerenderer.js @@ -8,8 +8,7 @@ import { withDataProviderBranch, withDataProvider, withData, - withLoading, - withRefresh + withLoading } from "helpers/data-provider"; import Loading from "./Loading"; @@ -21,9 +20,10 @@ const BooksListConnected = withDataProviderBranch(booksWithAuthorName, ["books", ); const WrapperConnected = withDataProvider(booksWithAuthorName, ["books", "isLoading"])(Wrapper); -const WrapperConnectedToDataAndLoading = withRefresh(booksWithAuthorName)( - withLoading(booksWithAuthorName, "isLoading")(withData(booksWithAuthorName, "books")(Wrapper)) -); +const WrapperConnectedToDataAndLoading = withLoading( + booksWithAuthorName, + "isLoading" +)(withData(booksWithAuthorName, "books")(Wrapper)); const BooksSearchRerendered = () => { const [currentRenders, changeCurrentRenders] = useState(0);