Skip to content

Commit

Permalink
Merge pull request #1203 from 18F/jk-bind-action-creators
Browse files Browse the repository at this point in the history
Bind action creators to dispatch for page level components and remove appState
  • Loading branch information
jeremiak authored Aug 15, 2017
2 parents d541a5f + 319f400 commit 7d82da1
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 69 deletions.
35 changes: 18 additions & 17 deletions src/App.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,16 @@ import Footer from './components/Footer'
import Glossary from './components/Glossary'
import Header from './components/Header'
import SkipContent from './components/SkipContent'
import * as feedbackActions from './actions/feedback'
import { hideFeedback, showFeedback } from './actions/feedback'
import * as glossaryActions from './actions/glossary'

const isProd = process.env.NODE_ENV === 'production'

const App = ({
actions,
appState,
children,
dispatch,
feedbackOpen,
glossary,
location,
sidebarOpen,
}) =>
Expand All @@ -31,33 +31,34 @@ const App = ({
<BetaBanner onFeedbackClick={actions.showFeedback} />
<Header location={location} />
<main className="site-main">
{children && React.cloneElement(children, { appState, dispatch })}
{children}
</main>
<Glossary actions={actions} {...appState.glossary} />
<Glossary actions={actions} {...glossary} />
<Footer actions={actions} />
{!isProd && <ClearCacheBtn />}
<Feedback
isOpen={appState.feedback.isOpen}
onClose={actions.hideFeedback}
/>
<Feedback isOpen={feedbackOpen} onClose={actions.hideFeedback} />
<Analytics />
</div>

App.propTypes = {
appState: PropTypes.object,
dispatch: PropTypes.func,
actions: PropTypes.shape({
hideFeedback: PropTypes.func,
showFeedback: PropTypes.func,
}),
feedbackOpen: PropTypes.bool,
glossary: PropTypes.object,
sidebarOpen: PropTypes.bool,
}

const mapStateToProps = state => {
const { isOpen: sidebarOpen } = state.sidebar
return { appState: state, sidebarOpen }
}
const mapStateToProps = ({ feedback, glossary, sidebar }) => ({
feedbackOpen: feedback.isOpen,
glossary,
sidebarOpen: sidebar.isOpen,
})

const mapDispatchToProps = dispatch => ({
dispatch,
actions: bindActionCreators(
{ ...feedbackActions, ...glossaryActions },
{ hideFeedback, showFeedback, ...glossaryActions },
dispatch,
),
})
Expand Down
16 changes: 12 additions & 4 deletions src/pages/About.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import PropTypes from 'prop-types'
import React from 'react'
import Helmet from 'react-helmet'
import { Link } from 'react-router'
import { connect } from 'react-redux'
import reduceEntries from 'reduce-entries'
import { bindActionCreators } from 'redux'

import SharingTags from '../components/SharingTags'
import Term from '../components/Term'
Expand Down Expand Up @@ -82,7 +84,7 @@ class About extends React.Component {
}

render() {
const { dispatch } = this.props
const { actions } = this.props
const { mapShown } = this.state
const toggles = [
{ disabled: !mapShown, type: 'table' },
Expand Down Expand Up @@ -261,7 +263,7 @@ class About extends React.Component {
</div>
<button
className="btn btn-primary"
onClick={() => dispatch(showFeedback())}
onClick={() => actions.showFeedback()}
type="button"
>
Submit feedback
Expand All @@ -274,7 +276,9 @@ class About extends React.Component {
}

About.propTypes = {
dispatch: PropTypes.func,
actions: PropTypes.shape({
showFeedback: PropTypes.func,
}),
}

const ParticipationMap = ({ states }) =>
Expand Down Expand Up @@ -355,4 +359,8 @@ const ParticipationTable = ({ states }) =>
</tbody>
</table>

export default About
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators({ showFeedback }, dispatch),
})

export default connect(null, mapDispatchToProps)(About)
14 changes: 5 additions & 9 deletions src/pages/DownloadsAndDocs.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,12 @@ import Helmet from 'react-helmet'
import DownloadBulkNibrs from '../components/DownloadBulkNibrs'
import DownloadDataBtn from '../components/DownloadDataBtn'
import SharingTags from '../components/SharingTags'
import Term from '../components/Term'
import { NibrsTerm } from '../components/Terms'
import otherDatasets from '../../content/datasets.yml'
import markdown from '../util/md'

const border = 'border-bottom border-blue-light'
const borderLight = 'border-bottom border-blue-lighter'
const nibrsTerm = (
<Term id="national incident-based reporting system (nibrs)" size="lg">
incident-based (NIBRS)
</Term>
)

const DownloadsAndDocs = () =>
<section className="bg-white">
Expand All @@ -28,9 +23,10 @@ const DownloadsAndDocs = () =>
<div className="clearfix">
<div className="md-col md-col-9 md-pr7 fs-16 sm-fs-20 serif">
<p className="mb2 md-m0">
Download {nibrsTerm} data by year and location. Estimated data and
other crime-related datasets are also available for download. Data
is provided as CSV files and can be accessed via the{' '}
Download <NibrsTerm size="lg" /> data by year and location.
Estimated data and other crime-related datasets are also available
for download. Data is provided as CSV files and can be accessed via
the{' '}
<a className="underline" href="/api">
Crime Data Explorer API
</a>.
Expand Down
54 changes: 33 additions & 21 deletions src/pages/Explorer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import startCase from 'lodash.startcase'
import PropTypes from 'prop-types'
import React from 'react'
import Helmet from 'react-helmet'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'

import AboutTheData from '../components/AboutTheData'
import AgencyChartContainer from '../containers/AgencyChartContainer'
Expand All @@ -25,8 +27,8 @@ import lookup from '../util/usa'

class Explorer extends React.Component {
componentDidMount() {
const { appState, dispatch, params, router } = this.props
const { since, until } = appState.filters
const { actions, filters, params, router } = this.props
const { since, until } = filters
const { query } = router.location
const { place, placeType } = getPlaceInfo(params)

Expand All @@ -35,45 +37,41 @@ class Explorer extends React.Component {
return yr >= 1960 && yr <= 2014 ? yr : alt
}

const filters = {
actions.updateApp({
...params,
place,
placeType,
...query,
since: clean(query.since, since),
until: clean(query.until, until),
}

dispatch(updateApp(filters))
})
}

componentWillReceiveProps({ params: newParams }) {
const { appState, dispatch } = this.props
const { place } = appState.filters
const { actions, filters } = this.props
const { crime } = newParams
const newPlace = getPlaceInfo(newParams)

if (place !== newPlace.place) {
dispatch(updateApp({ crime, ...newPlace }))
if (filters.place !== newPlace.place) {
actions.updateApp({ crime, ...newPlace })
}
}

handleSidebarChange = change => {
const { router } = this.props
this.props.dispatch(updateApp(change, router))
const { actions, router } = this.props
actions.updateApp(change, router)
}

toggleSidebar = () => {
const { dispatch } = this.props
const { actions } = this.props
const { isOpen } = this.props.appState.sidebar

if (isOpen) return dispatch(hideSidebar())
return dispatch(showSidebar())
if (isOpen) return actions.hideSidebar()
return actions.showSidebar()
}

render() {
const { appState, dispatch, params } = this.props
const { agencies, filters } = appState
const { actions, agencies, filters, params } = this.props
const { crime } = params
const { place, placeType } = getPlaceInfo(params)
const agency = placeType === 'agency' && getAgency(agencies, place)
Expand Down Expand Up @@ -123,7 +121,7 @@ class Explorer extends React.Component {
<NibrsContainer />
<AboutTheData
crime={crime}
onTermClick={term => dispatch(showTerm(term))}
onTermClick={term => actions.showTerm(term)}
/>
</div>
</div>
Expand All @@ -133,10 +131,24 @@ class Explorer extends React.Component {
}

Explorer.propTypes = {
appState: PropTypes.object,
dispatch: PropTypes.func,
actions: PropTypes.shape({
hideSidebar: PropTypes.func,
showSidebar: PropTypes.func,
showTerm: PropTypes.func,
updateApp: PropTypes.func,
}),
agencies: PropTypes.object,
filters: PropTypes.object,
params: PropTypes.object,
router: PropTypes.object,
}

export default Explorer
const mapStateToProps = ({ agencies, filters }) => ({ agencies, filters })
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators(
{ hideSidebar, showSidebar, showTerm, updateApp },
dispatch,
),
})

export default connect(mapStateToProps, mapDispatchToProps)(Explorer)
23 changes: 14 additions & 9 deletions src/pages/Home.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import React from 'react'
import Helmet from 'react-helmet'
import { connect } from 'react-redux'
import { Link } from 'react-router'
import { bindActionCreators } from 'redux'

import LocationSelect from '../components/LocationSelect'
import SharingTags from '../components/SharingTags'
Expand All @@ -16,7 +17,7 @@ import { slugify } from '../util/text'
import lookup from '../util/usa'
import dataPreview from '../../content/preview.yml'

const Home = ({ crime, dispatch, place, placeType, router }) => {
const Home = ({ actions, crime, place, placeType, router }) => {
const isValid = !!(crime && place) || false
const usState = placeType === 'agency' ? oriToState(place) : place

Expand All @@ -25,22 +26,21 @@ const Home = ({ crime, dispatch, place, placeType, router }) => {
if (!id) return

const placeNew = { place: lookup(id).slug, placeType: 'state' }
dispatch(updateFilters(placeNew))
dispatch(updateApp({ crime, ...placeNew }, router))
actions.updateFilters(placeNew)
actions.updateApp({ crime, ...placeNew }, router)
}

const handleSearchClick = () => {
const change = { crime, place: usState, placeType: 'state' }
dispatch(updateApp(change, router))
actions.updateApp(change, router)
}

const selectCrime = e => {
const action = updateFilters({ crime: slugify(e.target.value) })
dispatch(action)
actions.updateFilters({ crime: slugify(e.target.value) })
}

const selectLocation = e => {
dispatch(updateFilters(e))
actions.updateFilters(e)
}

return (
Expand Down Expand Up @@ -188,13 +188,18 @@ const Home = ({ crime, dispatch, place, placeType, router }) => {
}

Home.propTypes = {
actions: PropTypes.shape({
updateApp: PropTypes.func,
updateFilters: PropTypes.func,
}),
crime: PropTypes.string,
dispatch: PropTypes.func,
place: PropTypes.string,
placeType: PropTypes.string,
}

const mapStateToProps = ({ filters }) => ({ ...filters })
const mapDispatchToProps = dispatch => ({ dispatch })
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators({ updateApp, updateFilters }, dispatch),
})

export default connect(mapStateToProps, mapDispatchToProps)(Home)
23 changes: 14 additions & 9 deletions src/pages/NotFound.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,36 +3,41 @@ import PropTypes from 'prop-types'
import React from 'react'
import Helmet from 'react-helmet'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'

import Link from '../components/Link'
import { showFeedback } from '../actions/feedback'

const NotFound = ({ dispatch }) =>
const NotFound = ({ actions }) =>
<div className="container mb8 mx-auto px2 pt8">
<Helmet title="CDE :: 404" />
<h1 className="mt0 fs-40 col-12 sm-col-7">
We couldn{"'"}t find the page you are looking for.
</h1>
<p className="m0 mb4 fs-24 serif">Please check the link and try again.</p>
<Link to="/" className="btn btn-primary mb2 fs-18">Return home</Link>
<Link to="/" className="btn btn-primary mb2 fs-18">
Return home
</Link>
<p className="fs-18 serif">
If you still can't find what you're looking for, please
{' '}
If you still can't find what you're looking for, please{' '}
<button
className="bg-transparent bold border-none color-inherit underline cursor-pointer serif p0"
onClick={() => dispatch(showFeedback())}
onClick={() => actions.showFeedback()}
>
submit feedback
</button>
{' '}
</button>{' '}
or contact us.
</p>
</div>

NotFound.propTypes = {
dispatch: PropTypes.func.isRequired,
actions: PropTypes.shape({
showFeedback: PropTypes.func,
}),
}

const mapDispatchToProps = dispatch => ({ dispatch })
const mapDispatchToProps = dispatch => ({
actions: bindActionCreators({ showFeedback }, dispatch),
})

export default connect(null, mapDispatchToProps)(NotFound)

0 comments on commit 7d82da1

Please sign in to comment.