import React from "react"
import _ from "lodash"
export const joinPaths = (...paths) => paths.filter(Boolean).join(".")
export const Context = React.createContext({})
export const useForm = () => React.useContext(Context)
export const PathContext = React.createContext("")
export const withField = BaseComponent => props => {
const { data, set } = React.useContext(Context)
const path = React.useContext(PathContext)
const finalPath = joinPaths(path, props.path)
const value = finalPath ? _.get(data, finalPath) : data
const setValue = React.useCallback(val => set(finalPath, val), [finalPath])
return <BaseComponent setValue={setValue} value={value} {...props} />
}
export default class extends React.Component {
static getDerivedStateFromProps(props, state) {
const { initialData } = props
if (initialData !== state.initialData) {
return {
data: initialData,
initialData
}
}
return null
}
state = {
data: this.props.initialData || {},
set: (path, value) => {
let data = JSON.parse(JSON.stringify(this.state.data))
this.setState(_.set({ data }, `data.${path}`, value))
},
reset: () => {
this.setState({
data: this.props.initialData || {}
})
}
}
handleSubmit = e => {
e.preventDefault()
this.props.onSubmit(this.state.data, this.state)
}
render() {
// eslint-disable-next-line no-unused-vars
const { children, initialData, ...props } = this.props
const { Provider, Consumer } = Context
return (
<Provider value={this.state}>
<form {...props} onSubmit={this.handleSubmit}>
{typeof children === "function" ? <Consumer>{children}</Consumer> : children}
</form>
</Provider>
)
}
}
|