Skip to content

Instantly share code, notes, and snippets.

@robinweser
Created August 16, 2018 21:07
Show Gist options
  • Save robinweser/3d6c5796d4c1598089487adb2de9582a to your computer and use it in GitHub Desktop.
Save robinweser/3d6c5796d4c1598089487adb2de9582a to your computer and use it in GitHub Desktop.
react-controlled-form implemented with react-woodworm
import { Component } from 'react'
import { createStore } from 'react-woodworm'
const FormStore = createStore({
model: {
data: {},
state: {},
},
actions: {
updateField: ({ state, data }, payload) => {
const { fieldId, ...field } = payload
debugger
const prevField = data[fieldId] || {}
return {
state,
data: {
...data,
[fieldId]: {
...prevField,
...field,
},
},
}
},
updateState: ({ state, data }, payload) => ({
data,
state: {
...state,
...payload,
},
}),
},
})
class FormContainer extends Component {
componentWillReceiveProps(newProps) {
const { onChange, updateField, updateState, data, state } = this.props
if (onChange && data.firstname !== newProps.firstname) {
onChange({
data: newProps.data,
previousData: data,
state: newProps.state,
previousState: state,
updateField,
updateState,
})
}
}
render() {
return this.props.children
}
}
function Form({ initialFields = {}, initialState = {}, onChange, children }) {
const initialForm = {
data: initialFields,
state: initialState,
}
return (
<FormStore.Provider initialState={initialForm}>
<FormStore.Consumer>
{({ data, state }, { updateField, updateState }) => (
<FormContainer
data={data}
state={state}
updateField={updateField}
updateState={updateState}
onChange={onChange}>
{children}
</FormContainer>
)}
</FormStore.Consumer>
</FormStore.Provider>
)
}
const defaultField = {
value: '',
isEnabled: true,
isRequired: false,
isTouched: false,
isValid: true,
}
class FieldContainer extends Component {
static defaultProps = {
initialData: {},
data: {},
}
constructor(props, context) {
super(props, context)
const initialField = {
...defaultField,
...props.data,
...props.initialData,
}
props.updateField(initialField)
}
render() {
const { fieldId, updateField, data, children } = this.props
return children({
fieldId,
updateField,
data,
})
}
}
function Field({ fieldId, initialData, children }) {
return (
<FormStore.Consumer>
{({ data }, { updateField }) => (
<FieldContainer
fieldId={fieldId}
initialData={initialData}
data={data[fieldId]}
updateField={fieldData =>
updateField({ isTouched: true, ...fieldData, fieldId })
}>
{children}
</FieldContainer>
)}
</FormStore.Consumer>
)
}
function Consumer({ children }) {
return (
<FormStore.Consumer>
{({ data, state }, { updateField, updateState }) =>
children({ data, state, updateField, updateState })
}
</FormStore.Consumer>
)
}
export { Form, Field, Consumer }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment