Skip to content

Commit

Permalink
Refactor with redux persist example (vercel#13338)
Browse files Browse the repository at this point in the history
Related to [11014](vercel#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.
  • Loading branch information
todortotev authored and rokinsky committed Jul 11, 2020
1 parent 156bf65 commit 8395b03
Show file tree
Hide file tree
Showing 6 changed files with 77 additions and 121 deletions.
54 changes: 15 additions & 39 deletions 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 (
<div>
<h1>
Count: <span>{count}</span>
</h1>
<button onClick={this.increment}>+1</button>
<button onClick={this.decrement}>-1</button>
<button onClick={this.reset}>Reset</button>
</div>
)
}
}

function mapStateToProps(state) {
const { count } = state
return { count }
return (
<div>
<h1>
Count: <span>{counter}</span>
</h1>
<button onClick={() => dispatch(incrementCount())}>+1</button>
<button onClick={() => dispatch(decrementCount())}>-1</button>
<button onClick={() => dispatch(resetCount())}>Reset</button>
</div>
)
}
const mapDispatchToProps = (dispatch) =>
bindActionCreators({ incrementCount, decrementCount, resetCount }, dispatch)

export default connect(mapStateToProps, mapDispatchToProps)(Counter)
export default Counter
81 changes: 34 additions & 47 deletions 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 (
<div>
<h1>API DATA:</h1>
{exampleData && !isDataLoading ? (
<pre>
<code>{JSON.stringify(exampleData, null, 2)}</code>
</pre>
) : (
<p style={{ color: 'blue' }}>Loading...</p>
)}
{error && <p style={{ color: 'red' }}>Error fetching data.</p>}
</div>
)
}
}

function mapStateToProps(state) {
const { exampleData, error } = state
return { exampleData, error }
return (
<div>
<h1>API DATA:</h1>
{exampleData && !isLoading ? (
<pre>
<code>{JSON.stringify(exampleData, null, 2)}</code>
</pre>
) : (
<p style={{ color: 'blue' }}>Loading...</p>
)}
{error && <p style={{ color: 'red' }}>Error fetching data.</p>}
</div>
)
}
const mapDispatchToProps = (dispatch) =>
bindActionCreators({ loadExampleData, loadingExampleDataFailure }, dispatch)

export default connect(mapStateToProps, mapDispatchToProps)(DataList)
export default DataList
13 changes: 5 additions & 8 deletions 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 (
<div>
<Clock lastUpdate={lastUpdate} light={light} />
Expand All @@ -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
6 changes: 3 additions & 3 deletions examples/with-redux-persist/package.json
Expand Up @@ -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"
}
40 changes: 17 additions & 23 deletions 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 <Examples />
}

componentWillUnmount() {
clearInterval(this.timer)
}
export async function getStaticProps() {
const store = initializeStore()
store.dispatch(serverRenderClock())

render() {
return <Examples />
return {
props: {},
}
}
const mapDispatchToProps = { startClock }
export default connect(null, mapDispatchToProps)(Index)

export default Index
4 changes: 3 additions & 1 deletion examples/with-redux-persist/store.js
Expand Up @@ -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
}

0 comments on commit 8395b03

Please sign in to comment.