From 8395b03f24ce5fbee299cfca50afc0da04006f81 Mon Sep 17 00:00:00 2001 From: TodorTotev <51530311+TodorTotev@users.noreply.github.com> Date: Mon, 25 May 2020 20:28:39 +0300 Subject: [PATCH] Refactor with redux persist example (#13338) Related to [11014](https://github.com/zeit/next.js/issues/11014) First and most important, removed the getInitialProps and used getStaticProps. Then, I refactored Counter, DataList and Examples components. I have refactored them from class-based components to functional. Also in each component the redux implementation was refactored using the new hooks API, which resulted in ~40% less code. If you want me to change anything or you are not satisfied with any given change, I'm open to suggestions. --- .../with-redux-persist/components/counter.js | 54 ++++--------- .../components/data-list.js | 81 ++++++++----------- .../with-redux-persist/components/examples.js | 13 ++- examples/with-redux-persist/package.json | 6 +- examples/with-redux-persist/pages/index.js | 40 ++++----- examples/with-redux-persist/store.js | 4 +- 6 files changed, 77 insertions(+), 121 deletions(-) diff --git a/examples/with-redux-persist/components/counter.js b/examples/with-redux-persist/components/counter.js index 6adef11fe7569..c74c627c4a085 100644 --- a/examples/with-redux-persist/components/counter.js +++ b/examples/with-redux-persist/components/counter.js @@ -1,44 +1,20 @@ -import { Component } from 'react' -import { connect } from 'react-redux' -import { bindActionCreators } from 'redux' +import { useSelector, useDispatch } from 'react-redux' import { incrementCount, decrementCount, resetCount } from '../store' -class Counter extends Component { - increment = () => { - const { incrementCount } = this.props - incrementCount() - } +const Counter = () => { + const counter = useSelector((state) => state.count) + const dispatch = useDispatch() - decrement = () => { - const { decrementCount } = this.props - decrementCount() - } - - reset = () => { - const { resetCount } = this.props - resetCount() - } - - render() { - const { count } = this.props - return ( -
-

- Count: {count} -

- - - -
- ) - } -} - -function mapStateToProps(state) { - const { count } = state - return { count } + return ( +
+

+ Count: {counter} +

+ + + +
+ ) } -const mapDispatchToProps = (dispatch) => - bindActionCreators({ incrementCount, decrementCount, resetCount }, dispatch) -export default connect(mapStateToProps, mapDispatchToProps)(Counter) +export default Counter diff --git a/examples/with-redux-persist/components/data-list.js b/examples/with-redux-persist/components/data-list.js index 43bb9e97426bd..532558ddc3c1c 100644 --- a/examples/with-redux-persist/components/data-list.js +++ b/examples/with-redux-persist/components/data-list.js @@ -1,66 +1,53 @@ -import { Component } from 'react' -import { connect } from 'react-redux' -import { bindActionCreators } from 'redux' +import { useState } from 'react' +import { useSelector, useDispatch } from 'react-redux' import { loadExampleData, loadingExampleDataFailure } from '../store' +import { useEffect } from 'react' -class DataList extends Component { - state = { - isDataLoading: false, - } +const DataList = () => { + const dispatch = useDispatch() + const exampleData = useSelector((state) => state.exampleData) + const error = useSelector((state) => state.error) + const [isLoading, setIsLoading] = useState(false) - componentDidMount() { - const { loadExampleData, loadingExampleDataFailure } = this.props - const self = this + useEffect(() => { + setIsLoading(true) - this.setState({ isDataLoading: true }) window .fetch('https://jsonplaceholder.typicode.com/users') - .then(function (response) { + .then((response) => { if (response.status !== 200) { console.log( 'Looks like there was a problem. Status Code: ' + response.status ) - loadingExampleDataFailure() - self.setState({ isDataLoading: false }) + dispatch(loadingExampleDataFailure()) + setIsLoading(false) return } - response.json().then(function (data) { - loadExampleData(data) - self.setState({ isDataLoading: false }) + response.json().then((data) => { + dispatch(loadExampleData(data)) + setIsLoading(false) }) }) - .catch(function (err) { + .catch((err) => { console.log('Fetch Error :-S', err) - loadingExampleDataFailure() - self.setState({ isDataLoading: false }) + dispatch(loadingExampleDataFailure()) + setIsLoading(false) }) - } + }, [dispatch]) - render() { - const { exampleData, error } = this.props - const { isDataLoading } = this.state - - return ( -
-

API DATA:

- {exampleData && !isDataLoading ? ( -
-            {JSON.stringify(exampleData, null, 2)}
-          
- ) : ( -

Loading...

- )} - {error &&

Error fetching data.

} -
- ) - } -} - -function mapStateToProps(state) { - const { exampleData, error } = state - return { exampleData, error } + return ( +
+

API DATA:

+ {exampleData && !isLoading ? ( +
+          {JSON.stringify(exampleData, null, 2)}
+        
+ ) : ( +

Loading...

+ )} + {error &&

Error fetching data.

} +
+ ) } -const mapDispatchToProps = (dispatch) => - bindActionCreators({ loadExampleData, loadingExampleDataFailure }, dispatch) -export default connect(mapStateToProps, mapDispatchToProps)(DataList) +export default DataList diff --git a/examples/with-redux-persist/components/examples.js b/examples/with-redux-persist/components/examples.js index 19e2359fd54f0..85a5cc0c05c76 100644 --- a/examples/with-redux-persist/components/examples.js +++ b/examples/with-redux-persist/components/examples.js @@ -1,9 +1,11 @@ -import { connect } from 'react-redux' +import { useSelector } from 'react-redux' import Clock from './clock' import Counter from './counter' import DataList from './data-list' -function Examples({ lastUpdate, light }) { +const Examples = () => { + const lastUpdate = useSelector((state) => state.lastUpdate) + const light = useSelector((state) => state.light) return (
@@ -13,9 +15,4 @@ function Examples({ lastUpdate, light }) { ) } -function mapStateToProps(state) { - const { lastUpdate, light } = state - return { lastUpdate, light } -} - -export default connect(mapStateToProps)(Examples) +export default Examples diff --git a/examples/with-redux-persist/package.json b/examples/with-redux-persist/package.json index 23a93abe39b35..3d50e469b1c9d 100644 --- a/examples/with-redux-persist/package.json +++ b/examples/with-redux-persist/package.json @@ -10,10 +10,10 @@ "next": "latest", "react": "^16.7.0", "react-dom": "^16.7.0", - "react-redux": "^5.0.1", - "redux": "^3.6.0", + "react-redux": "7.2.0", + "redux": "4.0.5", "redux-devtools-extension": "^2.13.2", - "redux-persist": "^5.10.0" + "redux-persist": "6.0.0" }, "license": "ISC" } diff --git a/examples/with-redux-persist/pages/index.js b/examples/with-redux-persist/pages/index.js index f9245c6f433ec..a9e7ea64c7c10 100644 --- a/examples/with-redux-persist/pages/index.js +++ b/examples/with-redux-persist/pages/index.js @@ -1,30 +1,24 @@ -import { Component } from 'react' -import { connect } from 'react-redux' -import { startClock, serverRenderClock } from '../store' +import { useEffect } from 'react' +import { useDispatch } from 'react-redux' +import { startClock, serverRenderClock, initializeStore } from '../store' import Examples from '../components/examples' -class Index extends Component { - static getInitialProps({ reduxStore, req }) { - const isServer = !!req - // DISPATCH ACTIONS HERE ONLY WITH `reduxStore.dispatch` - reduxStore.dispatch(serverRenderClock(isServer)) +const Index = () => { + const dispatch = useDispatch() + useEffect(() => { + setInterval(() => dispatch(startClock(), 1000)) + }, [dispatch]) - return {} - } - - componentDidMount() { - // DISPATCH ACTIONS HERE FROM `mapDispatchToProps` - // TO TICK THE CLOCK - this.timer = setInterval(() => this.props.startClock(), 1000) - } + return +} - componentWillUnmount() { - clearInterval(this.timer) - } +export async function getStaticProps() { + const store = initializeStore() + store.dispatch(serverRenderClock()) - render() { - return + return { + props: {}, } } -const mapDispatchToProps = { startClock } -export default connect(null, mapDispatchToProps)(Index) + +export default Index diff --git a/examples/with-redux-persist/store.js b/examples/with-redux-persist/store.js index 1bcce762ae4e2..b44b630f3a008 100644 --- a/examples/with-redux-persist/store.js +++ b/examples/with-redux-persist/store.js @@ -90,9 +90,11 @@ const persistConfig = { const persistedReducer = persistReducer(persistConfig, reducer) export function initializeStore(initialState = exampleInitialState) { - return createStore( + const store = createStore( persistedReducer, initialState, composeWithDevTools(applyMiddleware()) ) + + return store }