Skip to content

Instantly share code, notes, and snippets.

@gram7gram
Last active January 18, 2017 16:20
Show Gist options
  • Save gram7gram/322d9a8415683eadc9f56ad215a3c0a7 to your computer and use it in GitHub Desktop.
Save gram7gram/322d9a8415683eadc9f56ad215a3c0a7 to your computer and use it in GitHub Desktop.
Stateless React Select with redux
"use strict";
import '../../../node_modules/react-select/dist/react-select.css';
import React from 'react';
import Select from 'react-select';
import {objectValues} from '../../Survey/utils';
import keyBy from 'lodash/keyBy';
import trans from '../translator';
class StatelessSelect extends React.Component {
constructor() {
super()
this.loadItems = this.loadItems.bind(this)
this.setItems = this.setItems.bind(this)
}
componentDidMount() {
this.props.preload && this.props.dispatch(this.props.fetchAction())
}
setItems(options) {
let items = false;
let selectedModels = false;
if (options) {
if (this.props.multi) {
items = options.map(option => this.props.collection.find(obj => obj.id === option.value))
.filter(item => item && item.id > 0);
selectedModels = options.map(option => this.props.selectedModels.find(obj => obj.id === option.value))
.filter(item => item && item.id > 0)
items = objectValues(keyBy(items.concat(selectedModels), 'id'))
} else {
items = this.props.collection.find(obj => obj.id === options.value);
}
}
this.props.dispatch(this.props.changeAction(items))
}
loadItems(search) {
if (this.props.isLoading) return;
if (search.length < this.props.minimumInputLength) return;
if (search === this.props.previousSearch) return;
if (!this.props.isLoaded) {
this.props.dispatch(this.props.fetchAction({filter: {search}}))
return;
}
search = search.trim().toUpperCase()
if (this.props.isLocal) {
const items = this.props.allOptions.filter(obj => obj.label.toUpperCase().indexOf(search) !== -1)
this.props.dispatch(this.props.filterAction(items, search, this.props.previousSearch))
} else {
this.props.dispatch(this.props.fetchAction({filter: {search}}))
}
}
render() {
return <Select
value={this.props.selectedOptions}
options={this.props.filteredOptions}
onChange={this.setItems}
onInputChange={this.loadItems}
{...this.props}
/>
}
}
StatelessSelect.propTypes = {
/** Access to store */
dispatch: React.PropTypes.func.isRequired,
/** Dispatch fetch collection on component mount */
fetchAction: React.PropTypes.func.isRequired,
/** Dispatch filter collection on input change */
filterAction: React.PropTypes.func.isRequired,
/** Dispatch on change */
changeAction: React.PropTypes.func.isRequired,
/** Select-friendly collection: [{label: '', value: ''}] */
allOptions: React.PropTypes.array,
/** Raw collection. Not select-friendly */
collection: React.PropTypes.array,
/** Select-friendly collection, that match input text: [{label: '', value: ''}] */
filteredOptions: React.PropTypes.array,
/** Select-friendly collection, that was selected: [{label: '', value: ''}] */
selectedOptions: React.PropTypes.any,
/** Raw collection, that was selected. Not select-friendly */
selectedModels: React.PropTypes.any,
/** Collection will be filtered, when search length is same or greater then this value */
minimumInputLength: React.PropTypes.number,
/** Previous search text */
previousSearch: React.PropTypes.string,
/** Fetch collection on component mount */
preload: React.PropTypes.any,
/** Should collection be loaded onle ONCE? */
isLocal: React.PropTypes.any,
}
StatelessSelect.defaultProps = {
minimumInputLength: 2,
preload: false,
isLocal: false,
noResultsText: trans.ru.noResultsText,
searchPromptText: trans.ru.searchPromptText,
placeholder: trans.ru.placeholder,
clearAllText: trans.ru.clearAllText,
clearValueText: trans.ru.clearValueText,
}
export default StatelessSelect
import fetchOrganizations from '../../actions/FetchOrganizations/Action'
import filterOrganizations from '../../actions/FilterOrganizations/Action'
import changeOrganizations from '../../actions/ChangeOrganizations/Action'
...
render() {
return (
<FormGroup validationState={!Validator.isValid && errors.customer ? "error" : null}>
<label>{trans.ru.orgCustomer}</label>
<StatelessSelect
preload={this.props.Customers.collection.length === 0 && !this.props.Customers.isLoading}
isLocal={true}
dispatch={this.props.dispatch}
fetchAction={fetchOrganizations}
filterAction={filterOrganizations}
changeAction={changeOrganizations}
{...this.props.Customers}
selectedModels={model.customer}
selectedOptions={model.customer ? {
value: model.customer.id,
label: getOrganizationLabel(model.customer)
} : null}
/>
{!Validator.isValid && errors.customer
? <HelpBlock>{errors.customer.message}</HelpBlock>
: null}
</FormGroup>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment