Skip to content

Instantly share code, notes, and snippets.

@rgdelato
Forked from ryanflorence/three-ways-same-UI.js
Created November 29, 2016 06:34
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rgdelato/3fd54065d9d5f0036832af964a11b943 to your computer and use it in GitHub Desktop.
Save rgdelato/3fd54065d9d5f0036832af964a11b943 to your computer and use it in GitHub Desktop.
// component state
class LedgerContainer extends React.Component {
state = {
debits: null,
credits: null,
creditsError: null,
debitsError: null
}
componentDidMount() {
fetchJSON('/debits').then(
(debits) => this.setState({ debits }),
(debitsError) => this.setState({ debitsError })
)
fetchJSON('/credits').then(
(credits) => this.setState({ credits }),
(creditsError) => this.setState({ creditsError })
)
}
render() {
const { credits, debits, creditsError, debitsError } = this.state
return (
<Ledger
credits={credits}
creditsError={creditsError}
debitsError={debitsError}
debits={debits}
/>
)
}
}
////////////////////////////////////////////////////////////////////////////////
// render callbacks - generalize the state and componentDidMount
class FetchJSON extends React.Component {
state = { data: null, error: null }
componentDidMount() {
fetchJSON(this.props.url).then(res => res.json()).then(
(data) => this.setState({ data }),
(error) => this.setState({ error })
)
}
render() {
return this.props.children(this.state)
}
}
class LedgerContainer extends React.Component {
render() {
return (
<FetchJSON url="/debits">
{({ data:debits, error:debitsError }) => (
<FetchJSON url="/credits">
{({ data:credits, error:creditsError }) => (
<Ledger
credits={credits}
creditsError={creditsError}
debitsError={debitsError}
debits={debits}
/>
)}
</FetchJSON>
)}
</FetchJSON>
)
}
}
////////////////////////////////////////////////////////////////////////////////
// redux + thunk middleware
const creditsReducer = (state={error: null data: null}, action) => {
if (action.type === 'CREDITS_ERROR') {
return { ...state, error: action.error }
} else if (action.type === 'CREDITS_LOADED') {
return { ...state, data: action.credits }
} else {
return state
}
}
const debitsReducer = (state={error: null data: null}, action) => {
if (action.type === 'DEBITS_ERROR') {
return { ...state, error: action.error }
} else if (action.type === 'DEBITS_LOADED') {
return { ...state, data: action.debits }
} else {
return state
}
}
const fetchCreditsAndDebits = () => (dispatch) => {
fetchJSON('/debits').then(
(debits) => dispatch({ type: 'DEBITS_LOADED', debits }),
(debitsError) => dispatch({ type: 'DEBITS_ERROR', debitsError })
)
fetchJSON('/credits').then(
(credits) => dispatch({ type: 'CREDITS_LOADED', credits }),
(creditsError) => dispatch({ type: 'CREDITS_ERROR', creditsError })
)
}
class LedgerContainer extends React.Component {
componentDidMount() {
this.props.dispatch(fetchCreditsAndDebits())
}
render() {
const { credits, debits, creditsError, debitsError } = this.props
return (
<Ledger
credits={credits}
creditsError={creditsError}
debitsError={debitsError}
debits={debits}
/>
)
}
}
export default connect((state) => {
return {
credits: state.credits.data,
debits: state.debits.data,
creditsError: state.credits.error,
debitsError: state.debits.error
}
})(LedgerContainer)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment