Skip to content

Instantly share code, notes, and snippets.

@rachelslurs
Last active July 31, 2017 22:29
Show Gist options
  • Save rachelslurs/eff5f22b70ffa485ee29e8d775834901 to your computer and use it in GitHub Desktop.
Save rachelslurs/eff5f22b70ffa485ee29e8d775834901 to your computer and use it in GitHub Desktop.
Passing a Redux-Form action creator from container to component via React context
import React, {Component} from 'react'
import {connect} from 'react-redux'
import PropTypes from 'prop-types'
import {reduxForm, change} from 'redux-form' // import the action creator you need
import CountryPicker from '../components/CountryPicker'
class CountriesContainer extends Component {
static propTypes = {
changeFieldValue: PropTypes.func.isRequired
}
static childContextTypes = {
changeFieldValue: PropTypes.func.isRequired
}
getChildContext() {
return {changeFieldValue: this.props.changeFieldValue}
}
render() {
return (
<div>
<CountryPicker/>
</div>
)
}
}
const mapStateToProps = undefined // if you don't need to mapStateToProps, just pass undefined
const mapDispatchToProps = (dispatch) => {
return {
// This will be passed as a property to this component
changeFieldValue: function(field, value) {
dispatch(change('rulesEditorForm', field, value))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(reduxForm({
form: 'countriesForm', // a unique identifier for this form
})(CountriesContainer))
import React, {Component} from 'react'
import {connect} from 'react-redux'
import PropTypes from 'prop-types'
import {Label, List, Checkbox, Table} from 'semantic-ui-react'
import indexOf from 'lodash/indexOf'
class CountryPicker extends Component {
constructor(props, context) {
super(props)
this.state = {
options: ['United States', 'Canada', 'Mexico'],
selected: ['United States'],
tempValue: ['United States']
}
}
static propTypes = {
options: PropTypes.array.isRequired,
selected: PropTypes.array.isRequired
}
static contextTypes = {
changeFieldValue: PropTypes.func.isRequired
}
componentDidUpdate(prevProps, prevState) {
const { tempValue } = this.state
this.context.changeFieldValue('countries', tempValue)
}
handleSelectAll = () => {
const { options, tempValue } = this.state
if (tempValue.length === options.length) {
// deselect all
this.setState({tempValue: []})
} else {
// select all
this.setState({tempValue: options})
}
}
handleChange = (e, {value}) => {
const { tempValue } = this.state
if (indexOf(tempValue, value) !== -1) {
tempValue.splice(indexOf(tempValue, value), 1)
this.setState({tempValue})
} else {
tempValue.push(value)
this.setState({tempValue})
}
}
render() {
const {options, tempValue, selected} = this.state
return (
<Table compact>
<Table.Header>
<Table.Row>
<Table.HeaderCell>
<Checkbox checked={options.length > 0 && tempValue.length === options.length} label='Countries'
indeterminate={0 !== tempValue.length && tempValue.length < options.length} onChange={this.handleSelectAll} onClick={this.handleSelectAll}
disabled={options.length === 0}/>
<Label circular horizontal>{tempValue.length}</Label>
</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(tempValue, 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