Open sonarforte opened 7 years ago
The issue is that no input-specific props (onChange
, onBlur
, onFocus
, etc.) were being passed into the actual input. Here's how you can refactor:
const UIInput = (props) => {
+ const { error, label, ...inputProps } = props;
return (
<div>
<label>{error ? "Error" : label}</label>
+ <input type="text" {...inputProps}></input>
</div>
)
}
Thanks for the tip, it certainly gives the desired behavior on the codepen example.
However, and I hate to keep going on about this, I have what is essentially the exact same code in my component and it doesn't work. The errors update correctly, but whenever there is a submit (failed or successful), the fields get cleared.
I've analyzed the rendered html and there seems to be no difference in the html tags or attributes on the form components. The only difference (aside from the behavior) that I've observed is on my machine there is a prevalence of rrf/batch
actions, which I do not see on the codepen example.
I'm really tearing my hair out as to why the same code works differently in two separate places, so I'm including (what I believe to be) all relevant files.
Thanks again for the help.
//package.json
{
"name": "widget",
"version": "0.1.0",
"private": true,
"devDependencies": {
"react-scripts": "0.9.0",
"redux-devtools-extension": "^2.13.2"
},
"dependencies": {
"babel-polyfill": "^6.23.0",
"classnames": "^2.2.5",
"crypto": "0.0.3",
"dns": "^0.2.2",
"isomorphic-fetch": "^2.2.1",
"jsonwebtoken": "^7.4.1",
"jws": "^3.1.4",
"jwt-simple": "^0.5.1",
"prop-types": "^15.5.10",
"react": "^15.5.4",
"react-dom": "^15.5.4",
"react-redux": "^5.0.5",
"react-redux-form": "^1.12.0",
"react-router": "^3.0.5",
"react-router-redux": "^4.0.8",
"redux": "^3.6.0",
"redux-logger": "^2.10.2",
"redux-saga": "^0.14.8",
"semantic-ui-css": "^2.2.10",
"semantic-ui-react": "^0.67.2",
"validator": "^7.0.0"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom",
"eject": "react-scripts eject"
}
}
// WidgetForm.js
import React, { Component } from 'react'
import { PropTypes } from 'prop-types'
import { connect } from 'react-redux'
import { Control, Form, } from 'react-redux-form'
import { widgetRequest, } from '../actions/'
//Same definition as codepen example
const UIInput = (props) => {
const { error, label, ...inputProps } = props;
console.log("UIINPUT Rendered")
console.log(inputProps)
return (
<div>
<label>{error ? "Error" : label}</label>
<input type="text" {...inputProps}></input>
</div>
)
}
class WidgetForm extends Component {
handleSubmit = (values) => {
const { client, widgetRequest } = this.props
console.log(values)
widgetRequest(values)
}
render() {
// Whether the field is empty
const isRequired = (val) => val && val.length > 0
// Whether to show the error message
const requiredError = (props) => {
const { touched, valid, focus } = props.fieldValue
return !focus && touched && !valid
}
return (
<Form
model="forms.widget"
onSubmit={(values) => this.handleSubmit(values)}
>
<Control.text
model=".name"
validators={{
isRequired,
}}
component={UIInput}
mapProps={{
label: "Name",
error: requiredError,
}}
/>
<Control.text
model=".number"
validators={{
isRequired,
}}
component={UIInput}
mapProps={{
label: "Number",
error: requiredError,
}}
/>
<Control.button
model="."
type="submit"
>
Submit
</Control.button>
</Form>
)
}
}
const mapStateToProps = (state, ownProps) => {
const { requesting, successful, } = state.forms.widget
return {
requesting,
successful,
}
}
export default connect(mapStateToProps, { widgetRequest })(WidgetForm)
// reducers/index.js
import { combineReducers } from 'redux';
import { combineForms } from 'react-redux-form';
import { syncHistoryWithStore, routerReducer } from 'react-router-redux'
// There are more things in real life but unrelated here
import { fooReducer as foo } from './foo'
import { widgetReducer as widget } from './widget'
const rootReducer = combineReducers({
foo: foo,
forms: combineForms({
widget: widget,
}, 'forms'),
routing: routerReducer,
});
export default rootReducer;
Let me know if there's something I missed. Thanks again.
This is more of a general question, but it seems that when my form is submitted and the field-level validation fails, it resets all the fields (even those that did not fail) to their default values of empty.
This might be similar, but not related to the issue spoken about relating to this example, where components are set to an error state after failed submission (even if that component is not in error).
Just type in one of the fields, hit submit, and you'll see that both fields are in error.
Unfortunately, I am unable to modify the above example to show the form resetting on failed submission. I have no idea how to explain this, as all the functional code is the same on my local project, but I think this issue might be general enough that there is a general method of accomplishing this that I have been unable to find in the docs.