From ce9963b6205ac6c7dc334d01d902425e3c338867 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 12:57:58 +0300 Subject: [PATCH 1/9] chore: Uninstall vanilla redux packages --- client/package-lock.json | 31 ------------------------------- client/package.json | 3 --- 2 files changed, 34 deletions(-) diff --git a/client/package-lock.json b/client/package-lock.json index 80aab93..3be196e 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -18,9 +18,6 @@ "react-redux": "^7.2.6", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", - "redux": "^4.1.2", - "redux-devtools-extension": "^2.13.9", - "redux-thunk": "^2.4.1", "web-vitals": "^1.1.2" } }, @@ -17513,22 +17510,6 @@ "@babel/runtime": "^7.9.2" } }, - "node_modules/redux-devtools-extension": { - "version": "2.13.9", - "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz", - "integrity": "sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==", - "peerDependencies": { - "redux": "^3.1.0 || ^4.0.0" - } - }, - "node_modules/redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", - "peerDependencies": { - "redux": "^4" - } - }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -35907,18 +35888,6 @@ "@babel/runtime": "^7.9.2" } }, - "redux-devtools-extension": { - "version": "2.13.9", - "resolved": "https://registry.npmjs.org/redux-devtools-extension/-/redux-devtools-extension-2.13.9.tgz", - "integrity": "sha512-cNJ8Q/EtjhQaZ71c8I9+BPySIBVEKssbPpskBfsXqb8HJ002A3KRVHfeRzwRo6mGPqsm7XuHTqNSNeS1Khig0A==", - "requires": {} - }, - "redux-thunk": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", - "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", - "requires": {} - }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", diff --git a/client/package.json b/client/package.json index 3e028a9..41a87f8 100644 --- a/client/package.json +++ b/client/package.json @@ -13,9 +13,6 @@ "react-redux": "^7.2.6", "react-router-dom": "^5.3.0", "react-scripts": "4.0.3", - "redux": "^4.1.2", - "redux-devtools-extension": "^2.13.9", - "redux-thunk": "^2.4.1", "web-vitals": "^1.1.2" }, "scripts": { From 5165cad114da0ddd854f65fe35654ed73f902a72 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 12:58:56 +0300 Subject: [PATCH 2/9] chore: Install redux-toolkit --- client/package-lock.json | 75 ++++++++++++++++++++++++++++++++++++++++ client/package.json | 1 + 2 files changed, 76 insertions(+) diff --git a/client/package-lock.json b/client/package-lock.json index 3be196e..08d0714 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -8,6 +8,7 @@ "name": "client", "version": "0.1.0", "dependencies": { + "@reduxjs/toolkit": "^1.7.1", "@testing-library/jest-dom": "^5.15.1", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", @@ -2773,6 +2774,38 @@ "node": ">= 8" } }, + "node_modules/@reduxjs/toolkit": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.7.1.tgz", + "integrity": "sha512-wXwXYjBVz/ItxB7SMzEAMmEE/FBiY1ze18N+VVVX7NtVbRUrdOGKhpQMHivIJfkbJvSdLUU923a/yAagJQzY0Q==", + "dependencies": { + "immer": "^9.0.7", + "redux": "^4.1.2", + "redux-thunk": "^2.4.1", + "reselect": "^4.1.5" + }, + "peerDependencies": { + "react": "^16.9.0 || ^17.0.0 || 18.0.0-beta", + "react-redux": "^7.2.1 || ^8.0.0-beta" + }, + "peerDependenciesMeta": { + "react": { + "optional": true + }, + "react-redux": { + "optional": true + } + } + }, + "node_modules/@reduxjs/toolkit/node_modules/immer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz", + "integrity": "sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -17510,6 +17543,14 @@ "@babel/runtime": "^7.9.2" } }, + "node_modules/redux-thunk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "peerDependencies": { + "redux": "^4" + } + }, "node_modules/regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -17708,6 +17749,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "node_modules/reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "node_modules/resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", @@ -24526,6 +24572,24 @@ } } }, + "@reduxjs/toolkit": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.7.1.tgz", + "integrity": "sha512-wXwXYjBVz/ItxB7SMzEAMmEE/FBiY1ze18N+VVVX7NtVbRUrdOGKhpQMHivIJfkbJvSdLUU923a/yAagJQzY0Q==", + "requires": { + "immer": "^9.0.7", + "redux": "^4.1.2", + "redux-thunk": "^2.4.1", + "reselect": "^4.1.5" + }, + "dependencies": { + "immer": { + "version": "9.0.7", + "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.7.tgz", + "integrity": "sha512-KGllzpbamZDvOIxnmJ0jI840g7Oikx58lBPWV0hUh7dtAyZpFqqrBZdKka5GlTwMTZ1Tjc/bKKW4VSFAt6BqMA==" + } + } + }, "@rollup/plugin-node-resolve": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-7.1.3.tgz", @@ -35888,6 +35952,12 @@ "@babel/runtime": "^7.9.2" } }, + "redux-thunk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.1.tgz", + "integrity": "sha512-OOYGNY5Jy2TWvTL1KgAlVy6dcx3siPJ1wTq741EPyUKfn6W6nChdICjZwCd0p8AZBs5kWpZlbkXW2nE/zjUa+Q==", + "requires": {} + }, "regenerate": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", @@ -36042,6 +36112,11 @@ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8=" }, + "reselect": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.5.tgz", + "integrity": "sha512-uVdlz8J7OO+ASpBYoz1Zypgx0KasCY20H+N8JD13oUMtPvSHQuscrHop4KbXrbsBcdB9Ds7lVK7eRkBIfO43vQ==" + }, "resize-observer-polyfill": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", diff --git a/client/package.json b/client/package.json index 41a87f8..20c2513 100644 --- a/client/package.json +++ b/client/package.json @@ -3,6 +3,7 @@ "version": "0.1.0", "private": true, "dependencies": { + "@reduxjs/toolkit": "^1.7.1", "@testing-library/jest-dom": "^5.15.1", "@testing-library/react": "^11.2.7", "@testing-library/user-event": "^12.8.3", From 1e30b84c60953c338f95f69d16b033dee9b6d664 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 14:16:55 +0300 Subject: [PATCH 3/9] chore: Minimal refactor using redux-toolkit patterns --- client/src/actions/propertyActions.js | 28 -------- client/src/actions/types.js | 3 - client/src/pages/PropertyListPage.js | 77 ++++++++++----------- client/src/reducers/index.js | 6 -- client/src/reducers/propertyReducers.js | 19 ----- client/src/store.js | 16 ----- client/src/store/index.js | 6 ++ client/src/store/property/propertySlice.js | 28 ++++++++ client/src/store/property/propertyThunks.js | 15 ++++ client/src/store/rootReducer.js | 6 ++ 10 files changed, 90 insertions(+), 114 deletions(-) delete mode 100644 client/src/actions/propertyActions.js delete mode 100644 client/src/actions/types.js delete mode 100644 client/src/reducers/index.js delete mode 100644 client/src/reducers/propertyReducers.js delete mode 100644 client/src/store.js create mode 100644 client/src/store/index.js create mode 100644 client/src/store/property/propertySlice.js create mode 100644 client/src/store/property/propertyThunks.js create mode 100644 client/src/store/rootReducer.js diff --git a/client/src/actions/propertyActions.js b/client/src/actions/propertyActions.js deleted file mode 100644 index adba19a..0000000 --- a/client/src/actions/propertyActions.js +++ /dev/null @@ -1,28 +0,0 @@ -import axios from "axios"; -import { - PROPERTY_LIST_FAIL, - PROPERTY_LIST_REQUEST, - PROPERTY_LIST_SUCCESS, -} from "./types"; - -export const listProperties = () => async (dispatch) => { - try { - dispatch({ - type: PROPERTY_LIST_REQUEST, - }); - const { data } = await axios.get("/api/v1/properties/all/"); - - dispatch({ - type: PROPERTY_LIST_SUCCESS, - payload: data, - }); - } catch (error) { - dispatch({ - type: PROPERTY_LIST_FAIL, - payload: - error.response && error.response.data.message - ? error.response.data.message - : error.message, - }); - } -}; diff --git a/client/src/actions/types.js b/client/src/actions/types.js deleted file mode 100644 index b19d675..0000000 --- a/client/src/actions/types.js +++ /dev/null @@ -1,3 +0,0 @@ -export const PROPERTY_LIST_REQUEST = "PROPERTY_LIST_REQUEST"; -export const PROPERTY_LIST_SUCCESS = "PROPERTY_LIST_SUCCESS"; -export const PROPERTY_LIST_FAIL = "PROPERTY_LIST_FAIL"; diff --git a/client/src/pages/PropertyListPage.js b/client/src/pages/PropertyListPage.js index 0602657..5b11fb8 100644 --- a/client/src/pages/PropertyListPage.js +++ b/client/src/pages/PropertyListPage.js @@ -1,49 +1,42 @@ -import { Alert, Col, Row, Spin } from "antd"; -import React, { useEffect } from "react"; -import { useDispatch, useSelector } from "react-redux"; -import { listProperties } from "../actions/propertyActions"; +import { Alert, Col, Row, Spin } from 'antd' +import React, { useEffect } from 'react' +import { useDispatch, useSelector } from 'react-redux' +import { fetchPropertyList } from '../store/property/propertyThunks' function PropertyListPage() { - const dispatch = useDispatch(); + const dispatch = useDispatch() - const propertiesList = useSelector((state) => state.propertiesList); + const propertiesList = useSelector((state) => state.propertiesList) - const { loading, error, properties } = propertiesList; + const { loading, error, properties } = propertiesList - useEffect(() => { - dispatch(listProperties()); - }, [dispatch]); - return ( - <> - {loading ? ( -
- -
- ) : error ? ( - - ) : ( - <> - - -

- Our Catalog of Properties -

- - {properties.map((property) => ( - -

{property.title}

- - ))} -
- - )} - - ); + useEffect(() => { + dispatch(fetchPropertyList()) + }, [dispatch]) + return ( + <> + {loading ? ( +
+ +
+ ) : error ? ( + + ) : ( + <> + + +

Our Catalog of Properties

+ + {properties.map((property) => ( + +

{property.title}

+ + ))} +
+ + )} + + ) } -export default PropertyListPage; +export default PropertyListPage diff --git a/client/src/reducers/index.js b/client/src/reducers/index.js deleted file mode 100644 index 3d9e46d..0000000 --- a/client/src/reducers/index.js +++ /dev/null @@ -1,6 +0,0 @@ -import { combineReducers } from "redux"; -import { propertiesListReducer } from "./propertyReducers"; - -export default combineReducers({ - propertiesList: propertiesListReducer, -}); diff --git a/client/src/reducers/propertyReducers.js b/client/src/reducers/propertyReducers.js deleted file mode 100644 index f19cb06..0000000 --- a/client/src/reducers/propertyReducers.js +++ /dev/null @@ -1,19 +0,0 @@ -import { - PROPERTY_LIST_FAIL, - PROPERTY_LIST_REQUEST, - PROPERTY_LIST_SUCCESS, -} from "../actions/types"; - -export const propertiesListReducer = (state = { properties: [] }, action) => { - switch (action.type) { - case PROPERTY_LIST_REQUEST: - return { loading: true, properties: [] }; - case PROPERTY_LIST_SUCCESS: - return { loading: false, properties: action.payload.results }; - - case PROPERTY_LIST_FAIL: - return { loading: false, error: action.payload }; - default: - return state; - } -}; diff --git a/client/src/store.js b/client/src/store.js deleted file mode 100644 index 97c24e3..0000000 --- a/client/src/store.js +++ /dev/null @@ -1,16 +0,0 @@ -import { applyMiddleware, createStore } from "redux"; -import { composeWithDevTools } from "redux-devtools-extension"; -import reduxThunk from "redux-thunk"; -import rootReducer from "./reducers"; - -const initialState = {}; - -const middleware = [reduxThunk]; - -const store = createStore( - rootReducer, - initialState, - composeWithDevTools(applyMiddleware(...middleware)) -); - -export default store; diff --git a/client/src/store/index.js b/client/src/store/index.js new file mode 100644 index 0000000..71ee5df --- /dev/null +++ b/client/src/store/index.js @@ -0,0 +1,6 @@ +import { configureStore } from '@reduxjs/toolkit' +import rootReducer from './rootReducer' + +const store = configureStore({ reducer: rootReducer }) + +export default store diff --git a/client/src/store/property/propertySlice.js b/client/src/store/property/propertySlice.js new file mode 100644 index 0000000..0b71607 --- /dev/null +++ b/client/src/store/property/propertySlice.js @@ -0,0 +1,28 @@ +import { createSlice } from '@reduxjs/toolkit' + +const initialState = { + properties: [], + loading: false, +} + +const propertiesSlice = createSlice({ + name: 'properties', + initialState, + reducers: { + propertyListRequest: (state, action) => { + state.loading = true + }, + propertyListSuccess: (state, action) => { + state.loading = false + state.properties = action.payload.results + }, + propertyListFail: (state, action) => { + state.loading = false + state.error = action.payload + }, + }, +}) + +export const { propertyListRequest, propertyListSuccess, propertyListFail } = propertiesSlice.actions + +export default propertiesSlice.reducer diff --git a/client/src/store/property/propertyThunks.js b/client/src/store/property/propertyThunks.js new file mode 100644 index 0000000..15ba067 --- /dev/null +++ b/client/src/store/property/propertyThunks.js @@ -0,0 +1,15 @@ +import axios from 'axios' + +import { propertyListRequest, propertyListSuccess, propertyListFail } from './propertySlice' + +export const fetchPropertyList = () => async (dispatch) => { + try { + dispatch(propertyListRequest()) + const { data } = await axios.get('/api/v1/properties/all/') + + dispatch(propertyListSuccess(data)) + } catch (error) { + const errorMessage = error.response && error.response.data.message ? error.response.data.message : error.message + dispatch(propertyListFail(errorMessage)) + } +} diff --git a/client/src/store/rootReducer.js b/client/src/store/rootReducer.js new file mode 100644 index 0000000..506a36a --- /dev/null +++ b/client/src/store/rootReducer.js @@ -0,0 +1,6 @@ +import { combineReducers } from 'redux' +import propertiesListReducer from './property/propertySlice' + +export default combineReducers({ + propertiesList: propertiesListReducer, +}) From 06aaaa7698c6761e1b59a93df9e53dfccfa25f92 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 15:10:07 +0300 Subject: [PATCH 4/9] chore: Add prettier config to conform to project code style --- client/.prettierrc.js | 8 +++ client/src/pages/PropertyListPage.js | 70 ++++++++++----------- client/src/store/index.js | 8 +-- client/src/store/property/propertySlice.js | 44 ++++++------- client/src/store/property/propertyThunks.js | 23 +++---- client/src/store/rootReducer.js | 8 +-- 6 files changed, 85 insertions(+), 76 deletions(-) create mode 100644 client/.prettierrc.js diff --git a/client/.prettierrc.js b/client/.prettierrc.js new file mode 100644 index 0000000..fd10541 --- /dev/null +++ b/client/.prettierrc.js @@ -0,0 +1,8 @@ +module.exports = { + semi: true, + trailingComma: "all", + singleQuote: false, + printWidth: 120, + tabWidth: 4, + useTabs: true, +}; diff --git a/client/src/pages/PropertyListPage.js b/client/src/pages/PropertyListPage.js index 5b11fb8..6ea1b29 100644 --- a/client/src/pages/PropertyListPage.js +++ b/client/src/pages/PropertyListPage.js @@ -1,42 +1,42 @@ -import { Alert, Col, Row, Spin } from 'antd' -import React, { useEffect } from 'react' -import { useDispatch, useSelector } from 'react-redux' -import { fetchPropertyList } from '../store/property/propertyThunks' +import { Alert, Col, Row, Spin } from "antd"; +import React, { useEffect } from "react"; +import { useDispatch, useSelector } from "react-redux"; +import { fetchPropertyList } from "../store/property/propertyThunks"; function PropertyListPage() { - const dispatch = useDispatch() + const dispatch = useDispatch(); - const propertiesList = useSelector((state) => state.propertiesList) + const propertiesList = useSelector((state) => state.propertiesList); - const { loading, error, properties } = propertiesList + const { loading, error, properties } = propertiesList; - useEffect(() => { - dispatch(fetchPropertyList()) - }, [dispatch]) - return ( - <> - {loading ? ( -
- -
- ) : error ? ( - - ) : ( - <> - - -

Our Catalog of Properties

- - {properties.map((property) => ( - -

{property.title}

- - ))} -
- - )} - - ) + useEffect(() => { + dispatch(fetchPropertyList()); + }, [dispatch]); + return ( + <> + {loading ? ( +
+ +
+ ) : error ? ( + + ) : ( + <> + + +

Our Catalog of Properties

+ + {properties.map((property) => ( + +

{property.title}

+ + ))} +
+ + )} + + ); } -export default PropertyListPage +export default PropertyListPage; diff --git a/client/src/store/index.js b/client/src/store/index.js index 71ee5df..01c7b3d 100644 --- a/client/src/store/index.js +++ b/client/src/store/index.js @@ -1,6 +1,6 @@ -import { configureStore } from '@reduxjs/toolkit' -import rootReducer from './rootReducer' +import { configureStore } from "@reduxjs/toolkit"; +import rootReducer from "./rootReducer"; -const store = configureStore({ reducer: rootReducer }) +const store = configureStore({ reducer: rootReducer }); -export default store +export default store; diff --git a/client/src/store/property/propertySlice.js b/client/src/store/property/propertySlice.js index 0b71607..ca253a7 100644 --- a/client/src/store/property/propertySlice.js +++ b/client/src/store/property/propertySlice.js @@ -1,28 +1,28 @@ -import { createSlice } from '@reduxjs/toolkit' +import { createSlice } from "@reduxjs/toolkit"; const initialState = { - properties: [], - loading: false, -} + properties: [], + loading: false, +}; const propertiesSlice = createSlice({ - name: 'properties', - initialState, - reducers: { - propertyListRequest: (state, action) => { - state.loading = true - }, - propertyListSuccess: (state, action) => { - state.loading = false - state.properties = action.payload.results - }, - propertyListFail: (state, action) => { - state.loading = false - state.error = action.payload - }, - }, -}) + name: "properties", + initialState, + reducers: { + propertyListRequest: (state, action) => { + state.loading = true; + }, + propertyListSuccess: (state, action) => { + state.loading = false; + state.properties = action.payload.results; + }, + propertyListFail: (state, action) => { + state.loading = false; + state.error = action.payload; + }, + }, +}); -export const { propertyListRequest, propertyListSuccess, propertyListFail } = propertiesSlice.actions +export const { propertyListRequest, propertyListSuccess, propertyListFail } = propertiesSlice.actions; -export default propertiesSlice.reducer +export default propertiesSlice.reducer; diff --git a/client/src/store/property/propertyThunks.js b/client/src/store/property/propertyThunks.js index 15ba067..c4bd5df 100644 --- a/client/src/store/property/propertyThunks.js +++ b/client/src/store/property/propertyThunks.js @@ -1,15 +1,16 @@ -import axios from 'axios' +import axios from "axios"; -import { propertyListRequest, propertyListSuccess, propertyListFail } from './propertySlice' +import { propertyListRequest, propertyListSuccess, propertyListFail } from "./propertySlice"; export const fetchPropertyList = () => async (dispatch) => { - try { - dispatch(propertyListRequest()) - const { data } = await axios.get('/api/v1/properties/all/') + try { + dispatch(propertyListRequest()); + const { data } = await axios.get("/api/v1/properties/all/"); - dispatch(propertyListSuccess(data)) - } catch (error) { - const errorMessage = error.response && error.response.data.message ? error.response.data.message : error.message - dispatch(propertyListFail(errorMessage)) - } -} + dispatch(propertyListSuccess(data)); + } catch (error) { + const errorMessage = + error.response && error.response.data.message ? error.response.data.message : error.message; + dispatch(propertyListFail(errorMessage)); + } +}; diff --git a/client/src/store/rootReducer.js b/client/src/store/rootReducer.js index 506a36a..7a6b448 100644 --- a/client/src/store/rootReducer.js +++ b/client/src/store/rootReducer.js @@ -1,6 +1,6 @@ -import { combineReducers } from 'redux' -import propertiesListReducer from './property/propertySlice' +import { combineReducers } from "redux"; +import propertiesListReducer from "./property/propertySlice"; export default combineReducers({ - propertiesList: propertiesListReducer, -}) + propertiesList: propertiesListReducer, +}); From 7e7a253deb4c4563d2cc721d9caee2c40470bdde Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 15:12:39 +0300 Subject: [PATCH 5/9] chore: Conform to frontend 80 character limit --- client/.prettierrc.js | 12 ++++++------ client/src/pages/PropertyListPage.js | 11 +++++++++-- client/src/store/property/propertySlice.js | 3 ++- client/src/store/property/propertyThunks.js | 10 ++++++++-- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/client/.prettierrc.js b/client/.prettierrc.js index fd10541..980c426 100644 --- a/client/.prettierrc.js +++ b/client/.prettierrc.js @@ -1,8 +1,8 @@ module.exports = { - semi: true, - trailingComma: "all", - singleQuote: false, - printWidth: 120, - tabWidth: 4, - useTabs: true, + semi: true, + trailingComma: "all", + singleQuote: false, + printWidth: 80, + tabWidth: 4, + useTabs: true, }; diff --git a/client/src/pages/PropertyListPage.js b/client/src/pages/PropertyListPage.js index 6ea1b29..cf608f7 100644 --- a/client/src/pages/PropertyListPage.js +++ b/client/src/pages/PropertyListPage.js @@ -20,12 +20,19 @@ function PropertyListPage() { ) : error ? ( - + ) : ( <> -

Our Catalog of Properties

+

+ Our Catalog of Properties +

{properties.map((property) => ( diff --git a/client/src/store/property/propertySlice.js b/client/src/store/property/propertySlice.js index ca253a7..cb31059 100644 --- a/client/src/store/property/propertySlice.js +++ b/client/src/store/property/propertySlice.js @@ -23,6 +23,7 @@ const propertiesSlice = createSlice({ }, }); -export const { propertyListRequest, propertyListSuccess, propertyListFail } = propertiesSlice.actions; +export const { propertyListRequest, propertyListSuccess, propertyListFail } = + propertiesSlice.actions; export default propertiesSlice.reducer; diff --git a/client/src/store/property/propertyThunks.js b/client/src/store/property/propertyThunks.js index c4bd5df..8eab898 100644 --- a/client/src/store/property/propertyThunks.js +++ b/client/src/store/property/propertyThunks.js @@ -1,6 +1,10 @@ import axios from "axios"; -import { propertyListRequest, propertyListSuccess, propertyListFail } from "./propertySlice"; +import { + propertyListRequest, + propertyListSuccess, + propertyListFail, +} from "./propertySlice"; export const fetchPropertyList = () => async (dispatch) => { try { @@ -10,7 +14,9 @@ export const fetchPropertyList = () => async (dispatch) => { dispatch(propertyListSuccess(data)); } catch (error) { const errorMessage = - error.response && error.response.data.message ? error.response.data.message : error.message; + error.response && error.response.data.message + ? error.response.data.message + : error.message; dispatch(propertyListFail(errorMessage)); } }; From 811df4bdcd4196acec213c1aa1f7e928b50247c5 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 17:13:45 +0300 Subject: [PATCH 6/9] fix: Properly handle error message updates in reducers --- client/src/store/property/propertySlice.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/src/store/property/propertySlice.js b/client/src/store/property/propertySlice.js index cb31059..e8ace0c 100644 --- a/client/src/store/property/propertySlice.js +++ b/client/src/store/property/propertySlice.js @@ -3,6 +3,7 @@ import { createSlice } from "@reduxjs/toolkit"; const initialState = { properties: [], loading: false, + error: undefined, // Optionally could be set to null or empty string. I find that undefined works best when using TypeScript }; const propertiesSlice = createSlice({ @@ -11,9 +12,11 @@ const propertiesSlice = createSlice({ reducers: { propertyListRequest: (state, action) => { state.loading = true; + state.error = undefined; }, propertyListSuccess: (state, action) => { state.loading = false; + state.error = undefined; state.properties = action.payload.results; }, propertyListFail: (state, action) => { From e807f01e813480505985755fcddc67aebf5d63db Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Thu, 30 Dec 2021 17:59:44 +0300 Subject: [PATCH 7/9] chore: Renaming a few files to stick to prior pluralization convetions --- client/src/pages/PropertyListPage.js | 2 +- .../src/store/property/{propertySlice.js => propertiesSlice.js} | 0 .../store/property/{propertyThunks.js => propertiesThunks.js} | 2 +- client/src/store/rootReducer.js | 2 +- 4 files changed, 3 insertions(+), 3 deletions(-) rename client/src/store/property/{propertySlice.js => propertiesSlice.js} (100%) rename client/src/store/property/{propertyThunks.js => propertiesThunks.js} (94%) diff --git a/client/src/pages/PropertyListPage.js b/client/src/pages/PropertyListPage.js index cf608f7..311b57d 100644 --- a/client/src/pages/PropertyListPage.js +++ b/client/src/pages/PropertyListPage.js @@ -1,7 +1,7 @@ import { Alert, Col, Row, Spin } from "antd"; import React, { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; -import { fetchPropertyList } from "../store/property/propertyThunks"; +import { fetchPropertyList } from "../store/property/propertiesThunks"; function PropertyListPage() { const dispatch = useDispatch(); diff --git a/client/src/store/property/propertySlice.js b/client/src/store/property/propertiesSlice.js similarity index 100% rename from client/src/store/property/propertySlice.js rename to client/src/store/property/propertiesSlice.js diff --git a/client/src/store/property/propertyThunks.js b/client/src/store/property/propertiesThunks.js similarity index 94% rename from client/src/store/property/propertyThunks.js rename to client/src/store/property/propertiesThunks.js index 8eab898..8c4baeb 100644 --- a/client/src/store/property/propertyThunks.js +++ b/client/src/store/property/propertiesThunks.js @@ -4,7 +4,7 @@ import { propertyListRequest, propertyListSuccess, propertyListFail, -} from "./propertySlice"; +} from "./propertiesSlice"; export const fetchPropertyList = () => async (dispatch) => { try { diff --git a/client/src/store/rootReducer.js b/client/src/store/rootReducer.js index 7a6b448..f50c501 100644 --- a/client/src/store/rootReducer.js +++ b/client/src/store/rootReducer.js @@ -1,5 +1,5 @@ import { combineReducers } from "redux"; -import propertiesListReducer from "./property/propertySlice"; +import propertiesListReducer from "./property/propertiesSlice"; export default combineReducers({ propertiesList: propertiesListReducer, From 2a401407d08808d9451c7687597c523e1ee914b6 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Fri, 31 Dec 2021 00:48:35 +0300 Subject: [PATCH 8/9] fix: Remove explicit call to combineReducers --- client/src/store/index.js | 6 +++++- client/src/store/rootReducer.js | 6 ------ 2 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 client/src/store/rootReducer.js diff --git a/client/src/store/index.js b/client/src/store/index.js index 01c7b3d..daf1978 100644 --- a/client/src/store/index.js +++ b/client/src/store/index.js @@ -1,5 +1,9 @@ import { configureStore } from "@reduxjs/toolkit"; -import rootReducer from "./rootReducer"; +import propertiesListReducer from "./property/propertiesSlice"; + +const rootReducer = { + propertiesList: propertiesListReducer, +}; const store = configureStore({ reducer: rootReducer }); diff --git a/client/src/store/rootReducer.js b/client/src/store/rootReducer.js deleted file mode 100644 index f50c501..0000000 --- a/client/src/store/rootReducer.js +++ /dev/null @@ -1,6 +0,0 @@ -import { combineReducers } from "redux"; -import propertiesListReducer from "./property/propertiesSlice"; - -export default combineReducers({ - propertiesList: propertiesListReducer, -}); From 0f55d8c8612f42a077d30c3f46e422a6b5bbd6c6 Mon Sep 17 00:00:00 2001 From: Cesar Napoleon Mejia Date: Fri, 31 Dec 2021 16:01:51 +0300 Subject: [PATCH 9/9] feat: Create reusable loader and error components (avoids nested ternaies) --- .../components/common/ReusableErrorAlert.js | 15 +++++++ .../src/components/common/ReusableLoader.js | 12 ++++++ client/src/pages/PropertyListPage.js | 43 +++++++------------ 3 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 client/src/components/common/ReusableErrorAlert.js create mode 100644 client/src/components/common/ReusableLoader.js diff --git a/client/src/components/common/ReusableErrorAlert.js b/client/src/components/common/ReusableErrorAlert.js new file mode 100644 index 0000000..df2ed6b --- /dev/null +++ b/client/src/components/common/ReusableErrorAlert.js @@ -0,0 +1,15 @@ +import React from "react"; +import { Alert } from "antd"; + +const ReusableErrorAlert = ({ error }) => { + return error ? ( + + ) : null; +}; + +export default ReusableErrorAlert; diff --git a/client/src/components/common/ReusableLoader.js b/client/src/components/common/ReusableLoader.js new file mode 100644 index 0000000..babb4d6 --- /dev/null +++ b/client/src/components/common/ReusableLoader.js @@ -0,0 +1,12 @@ +import React from "react"; +import { Spin } from "antd"; + +const ReusableLoader = ({ loading }) => { + return loading ? ( +
+ +
+ ) : null; +}; + +export default ReusableLoader; diff --git a/client/src/pages/PropertyListPage.js b/client/src/pages/PropertyListPage.js index 311b57d..d2ae683 100644 --- a/client/src/pages/PropertyListPage.js +++ b/client/src/pages/PropertyListPage.js @@ -1,7 +1,9 @@ -import { Alert, Col, Row, Spin } from "antd"; +import { Col, Row } from "antd"; import React, { useEffect } from "react"; import { useDispatch, useSelector } from "react-redux"; import { fetchPropertyList } from "../store/property/propertiesThunks"; +import ReusableLoader from "../components/common/ReusableLoader"; +import ReusableErrorAlert from "../components/common/ReusableErrorAlert"; function PropertyListPage() { const dispatch = useDispatch(); @@ -15,33 +17,18 @@ function PropertyListPage() { }, [dispatch]); return ( <> - {loading ? ( -
- -
- ) : error ? ( - - ) : ( - <> - - -

- Our Catalog of Properties -

- - {properties.map((property) => ( - -

{property.title}

- - ))} -
- - )} + + + + +

Our Catalog of Properties

+ + {properties.map((property) => ( + +

{property.title}

+ + ))} +
); }