Skip to content

Instantly share code, notes, and snippets.

@smashercosmo
Last active February 14, 2018 13:33
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 smashercosmo/ca211deee43e7f1b2b91ec38ff0aa37a to your computer and use it in GitHub Desktop.
Save smashercosmo/ca211deee43e7f1b2b91ec38ff0aa37a to your computer and use it in GitHub Desktop.
bla
import React from 'react'
import { noop } from 'lodash'
import hoistStatics from 'hoist-non-react-statics'
import { getServerErrorMessage } from '../../lib/serverErrorUtils'
import PropTypes from "prop-types"
function getDisplayName(WrappedComponent) {
return WrappedComponent.displayName || WrappedComponent.name || 'Component'
}
export default function formState({
pendingProp = 'pending',
errorProp = 'error',
onSubmit = noop,
}) {
return WrappedComponent => {
class FormState extends React.Component {
static contextTypes = {
store: PropTypes.object.isRequired,
}
state = {
error: '',
pending: false,
}
onSuccess = () => {
this.setState({ pending: false })
}
onError = error => {
this.setState({
pending: false,
error: getServerErrorMessage(error.code) || 'Something went wrong',
})
}
onSubmit = data => {
const { onSuccess, onError } = this
onSubmit({
data,
dispatch: this.context.store.dispatch,
onError,
onSuccess,
})
}
render() {
const formStateProps = {
[pendingProp]: this.state.pending,
[errorProp]: this.state.error,
}
return (
<WrappedComponent
{...this.props}
{...formStateProps}
onSubmit={onSubmit}
/>
)
}
}
FormState.displayName = `FormState(${getDisplayName(WrappedComponent)})`
return hoistStatics(FormState, WrappedComponent)
}
}
import React, { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import reduxForm from 'redux-form/es/reduxForm'
import Button from '../../components/Button/Button'
import TextField from '../../components/TextField/TextField'
import EditableField from '../../components/EditableField/EditableField'
import Alert from '../../components/Alert/Alert'
import formState from '../../components/FormState/FormState'
import { addCredits } from '../../redux/auth/auth.actions'
import { getUserCredits } from '../../redux/selectors'
import style from './AddCreditsForm.less'
const reduxFormConfig = {
form: 'addCredits',
}
const mapStateToProps = state => ({
userCredits: getUserCredits(state),
})
class AddCreditsForm extends Component {
static propTypes = {
// props from formState HOC
pending: PropTypes.bool.isRequired,
error: PropTypes.string.isRequired,
userCredits: PropTypes.string.isRequired,
}
render() {
return (
<div>
{this.props.error && (
<Alert type="error" className={style.error}>
{this.props.error}
</Alert>
)}
<form onSubmit={this.props.handleSubmit(this.onSubmit)} noValidate>
<EditableField
name="Available Store Credit"
value={this.props.userCredits}
static
/>
<TextField
id="add-credits-form-credits"
label="Credit code"
name="credit-code"
required
/>
<Button type="submit" theme="basic" pending={this.props.pending}>
Apply credit to my account
</Button>
</form>
</div>
)
}
}
const ReduxForm = reduxForm(reduxFormConfig)(AddCreditsForm)
const WithFormState = formState({
onSubmit({ data, dispatch, onError, onSuccess }) {
dispatch(
addCredits({
data,
onError,
onSuccess,
}),
)
},
})(ReduxForm)
const ConnectedForm = connect(mapStateToProps)(WithFormState)
export { ConnectedForm as AddCreditsForm }
export default WithFormState
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment