TypeError: Invalid attempt to destructure non-iterable instance
Sorry, I am sure this is my mistake, but hopefully you can help anyway
I have a simple form,
import React from 'react'
import revalidation from 'revalidation'
const SimpleForm = ({
reValidation: { form, updateValue, errors = {}, validateAll },
onSubmit
}) =>
<form
onSubmit={e => {
e.preventDefault()
validateAll(onSubmit)
}}
>
<div>
<label>Name (Required):</label>
<input
type="text"
value={form.name}
onChange={e => updateValue('name', e.target.value)}
/>
</div>
<input type="submit" value="Submit" />
</form>
export default revalidation(SimpleForm)
Which I then reference from my app,
import React from 'react'
import { render } from 'react-dom'
import SimpleForm from './components/SimpleForm'
const notEmpty = val => val !== ''
const validationRules = {
name: [notEmpty, 'Name cannot be empty']
}
class App extends React.Component {
constructor(props) {
super(props)
this.state = { } }
}
render() {
return (
<SimpleForm
onSubmit={this.onSubmit}
initialState={this.state.form}
rules={validationRules}
instantValidation={true}
validateSingle={true}
/>
)
}
}
render(<App />, document.getElementById('root'))
When I pass initialState={}, I get this error in the console as soon as I type:
index.js:40 Uncaught TypeError: Invalid attempt to destructure non-iterable instance
at index.js:40
at runPredicate (index.js:70)
at index.js:94
at _map (_map.js:6)
at map (map.js:57)
at _dispatchable.js:39
at f2 (_curry2.js:25)
at XWrap.f (index.js:93)
at XWrap.module.exports.XWrap.@@transducer/step (_xwrap.js:10)
at _arrayReduce (_reduce.js:11)
at _reduce (_reduce.js:44)
at f3 (_curry3.js:35)
at index.js:87
at _curryN.js:37
at _arity.js:6
at HigherOrderFormComponent.render (Revalidation.js:158)
at ReactCompositeComponent.js:796
at measureLifeCyclePerf (ReactCompositeComponent.js:75)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (ReactCompositeComponent.js:795)
at ReactCompositeComponentWrapper._renderValidatedComponent (ReactCompositeComponent.js:822)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:362)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at ReactCompositeComponentWrapper.performInitialMount (ReactCompositeComponent.js:371)
at ReactCompositeComponentWrapper.mountComponent (ReactCompositeComponent.js:258)
at Object.mountComponent (ReactReconciler.js:46)
at mountComponentIntoNode (ReactMount.js:104)
at ReactReconcileTransaction.perform (Transaction.js:140)
at batchedMountComponentIntoNode (ReactMount.js:126)
at ReactDefaultBatchingStrategyTransaction.perform (Transaction.js:140)
at Object.batchedUpdates (ReactDefaultBatchingStrategy.js:62)
at Object.batchedUpdates (ReactUpdates.js:97)
at Object._renderNewRootComponent (ReactMount.js:320)
at Object._renderSubtreeIntoContainer (ReactMount.js:401)
at render (ReactMount.js:422)
at Object.<anonymous> (index.js:28)
at __webpack_require__ (bootstrap 21f2308…:659)
at fn (bootstrap 21f2308…:85)
at Object.validateFormat (fetch.js:461)
at __webpack_require__ (bootstrap 21f2308…:659)
at module.exports.ctor.super_ (bootstrap 21f2308…:708)
at bundle.js:712
If I pass initialState={ form: { name: 'Alex' } }, I see that same error immediately, in the browser:

Link: https://www.dropbox.com/s/22exefba9wzuemm/Screenshot%202017-06-26%2012.28.29.png?dl=0
Any idea what could be happening here?
Yes, I can see why this is confusing. This doesn't work initialState={{name: 'foo'}}?
Passing in initialState={ form: ....} will break, should be initialState={{ form: {name: 'foo'} }} to not break, but it should be initialState={{name: 'foo'}}. Otherwise form would be the field we want to validate.
Passing in initialState={} will lead to the errors.
Should add a default for initialState, to fall back to an empty object.
I think there are two reasons why this is confusing:
1.) initialState implies that one can pass in more than the actual form field values. That's why initialState should be renamed to initialModel probably.
2.) The examples initialize the state with this.state = {form: {...}}
But then pass in initialState={this.state.form}, this detail is overlooked, it could also imply that the complete state could be passed in like so initialState={this.state} (which wouldn't work in this specific case.
Actually, I made a mistake in my original issue. The value I am passing is, this.state.form:
<SimpleForm
onSubmit={this.onSubmit}
initialState={this.state.form}
rules={validationRules}
instantValidation={true}
validateSingle={true}
/>
This doesn't work initialState={{name: 'foo'}}?
No, same error
The rules object is is the problem:
const validationRules = { name: [[notEmpty, 'Name cannot be empty']]}
Told you it was my mistake, thanks man!
Again, I think a guard clause here could be nice. Flow and TS definitions will also help avoid this error.
In the meantime, I hope people with the same problem can easily find this issue!
Yes, good point. We'll add some dev logging mechanism and sane defaults. Regarding TS and Flow, yes - let's add them.