Created
November 7, 2017 21:56
-
-
Save rachelslurs/99703a490c247070fba089c50cc0e824 to your computer and use it in GitHub Desktop.
Handling a change to Redux-Form data from container to component via props
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react' | |
import {connect} from 'react-redux' | |
import PropTypes from 'prop-types' | |
import {FieldArray, getFormValues} from 'redux-form' // import the action creator you need | |
import CountryPicker from '../components/CountryPicker' | |
class CountriesContainer extends Component { | |
constructor(props) { | |
super(props) | |
this.state = { countries: props.formValues.countries } | |
} | |
static propTypes = { | |
formValues: PropTypes.object | |
} | |
componentWillReceiveProps = (nextProps) => { | |
if (nextProps.formValues && nextProps.formValues.countries !== this.props.formValues.countries) { | |
this.setState({countries: nextProps.formValues.countries}) | |
} | |
} | |
shouldComponentUpdate = (nextProps) => { | |
if (nextProps.formValues) return (nextProps.formValues.countries !== this.props.formValues.countries) | |
} | |
handleCountryChange = () => this.setState({countries: this.props.formValues.countries}) | |
render() { | |
const { countries } = this.state | |
const options = ['United States', 'Canada', 'Mexico'] | |
return ( | |
<div> | |
<FieldArray component={CountryPicker} | |
name='countries' | |
options={options} | |
selectedCountries={countries} | |
onCountryChange={this.handleCountryChange} | |
/> | |
</div> | |
) | |
} | |
} | |
const mapStateToProps = (state) => { | |
const {countries} = state | |
return { | |
countries, | |
formValues: getFormValues('countriesForm')(state) | |
} | |
} | |
export default connect( | |
mapStateToProps | |
)(CountriesContainer) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, {Component} from 'react' | |
import {connect} from 'react-redux' | |
import PropTypes from 'prop-types' | |
import {List, Checkbox, Table} from 'semantic-ui-react' | |
import indexOf from 'lodash/indexOf' | |
class CountryPicker extends Component { | |
constructor(props) { | |
super(props) | |
this.state = { | |
options: props.options, | |
selected: props.selectedCountries, | |
fields: props.fields | |
} | |
this.handleCountryChange = this.handleCountryChange.bind(this) | |
} | |
static propTypes = { | |
options: PropTypes.array.isRequired, | |
selectedCountries: PropTypes.array.isRequired, | |
fields: PropTypes.any, | |
onCountryChange: PropTypes.func.isRequired | |
} | |
shouldComponentUpdate(nextProps) { | |
if (nextProps.selectedCountries !== this.props.selectedCountries) { | |
this.handleCountryChange() | |
return true | |
} | |
return false | |
} | |
componentWillReceiveProps(nextProps) { | |
this.setState({ | |
selected: nextProps.selectedCountries | |
}) | |
} | |
handleCountryChange() { | |
this.props.onCountryChange(this.state.regionKey) | |
} | |
handleSelectAll = () => { | |
const { options, selected, fields } = this.state | |
let fieldsToAdd, fieldsToRemove | |
if (selected.length === options.length) { | |
// deselect all | |
fieldsToRemove = selected.map((country) => indexOf(selected, country)) | |
// Making sure the removal of indices won't be affected by race conditions | |
// by sorting them in descending order | |
fieldsToRemove.sort((a, b) => b - a) | |
fieldsToRemove.forEach((countryIndex) => fields.remove(countryIndex)) | |
} else { | |
fieldsToAdd = options.reduce((result, country) => { | |
if (indexOf(selected, country) === -1 ) result.push(country) | |
return result | |
}, []) | |
fieldsToAdd.forEach((country) => fields.push(country)) | |
} | |
} | |
handleChange = (e, {value}) => { | |
const { selected, fields } = this.state | |
if (indexOf(selected, value) !== -1) { | |
fields.remove(indexOf(selected, value)) | |
} else { | |
fields.push(value) | |
} | |
} | |
render() { | |
const {options, selected} = this.state | |
return ( | |
<Table compact> | |
<Table.Header> | |
<Table.Row> | |
<Table.HeaderCell> | |
<Checkbox checked={options.length > 0 && selected.length === options.length} label='Countries' | |
indeterminate={0 !== selected.length && selected.length < options.length} onChange={this.handleSelectAll} onClick={this.handleSelectAll} | |
disabled={options.length === 0}/> | |
</Table.HeaderCell> | |
</Table.Row> | |
</Table.Header> | |
<Table.Body> | |
<Table.Row> | |
<Table.Cell> | |
<List verticalAlign='middle' relaxed style={{height:'180px', overflowY: 'auto'}}> | |
{options.map((country, i) => | |
<List.Item key={i}> | |
<List.Content> | |
<Checkbox label={country} name='countries' value={country} checked={indexOf(selected, country) !== -1} onChange={this.handleChange} /> | |
</List.Content> | |
</List.Item> | |
)} | |
</List> | |
</Table.Cell> | |
</Table.Row> | |
</Table.Body> | |
</Table> | |
) | |
} | |
} | |
export default CountryPicker |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment