无法编辑文本输入反应 redux 表单
Posted
技术标签:
【中文标题】无法编辑文本输入反应 redux 表单【英文标题】:Not able to edit text input react redux form 【发布时间】:2018-05-18 17:25:07 【问题描述】:从数据库设置值后无法编辑文本输入。该值会被最近键入的一个字符更改,同时从该文本输入中集中注意力。最初,我通过 state 属性设置 textinput 的每个值。然后编辑模式我从 db 获取该值并通过 state 属性进行设置。之后,我无法在编辑模式下进行编辑。
import React,
Component
from 'react';
import ReactDOM from 'react-dom';
import
Field,
reduxForm
from 'redux-form';
import _ from 'lodash';
import
addEmployee
from '../actions/employeeAction';
import
editEmployee
from '../actions/employeeAction';
import
connect
from 'react-redux';
import UploadImage from './uploadimage/uploadImage';
import
Redirect
from 'react-router-dom';
import Init from './index';
const FIELDS =
firstname:
type: 'input',
label: 'First Name',
key: 1,
name: 'firstname',
dbName: 'firstname'
,
lastname:
type: 'input',
label: 'Last Name',
key: 2,
name: 'lastname',
dbName: 'lastname'
,
password:
type: 'input',
label: 'Password',
key: 3,
name: 'password',
dbName: 'password'
,
reenterpassword:
type: 'input',
label: 'Re-password',
key: 4,
name: 'reenterpassword',
dbName: 'reenterpassword'
,
age:
type: 'Number',
label: 'Age',
key: 5,
name: 'age',
dbName: 'age'
,
occupation:
type: 'input',
label: 'Occupation',
key: 6,
name: 'occupation',
dbName: 'occupation'
,
city:
type: 'input',
label: 'City',
key: 7,
name: 'city',
dbName: 'city'
,
state:
type: 'input',
label: 'State',
key: 8,
name: 'state',
dbName: 'state'
,
pin:
type: 'input',
label: 'Pin',
key: 9,
name: 'pin',
dbName: 'pin'
,
phone:
type: 'input',
label: 'Phone',
key: 10,
name: 'phone',
dbName: 'phone'
,
email:
type: 'email',
label: 'Email',
key: 11,
name: 'email',
dbName: 'email'
,
dateOfJoin:
type: 'date',
label: 'Date Of Join',
key: 12,
name: 'dateOfJoin',
dbName: 'dateOfJoin'
,
uploadPhoto:
type: 'blob',
label: 'Upload Image',
key: 13,
name: 'uploadPhoto',
dbName: 'croppedImage'
class PostNew extends Component
constructor()
super();
this.renderField = this.renderField.bind(this);
this.onCroppedImgData = this.onCroppedImgData.bind(this);
this.valueChange = this.valueChange.bind(this);
this.state =
croppedData: undefined,
header: 'Registration Form',
createdUser: false
;
/********Initial setup for state for each text input********/
_.each(FIELDS, (type, field) =>
let dbState = type.dbName;
this.state =
dbState: ""
;
);
componentWillMount()
if (this.props.header)
this.setState(
header: this.props.header
);
if (this.props.userData)
_.each(FIELDS, (type, field) =>
let dbState = type.dbName;
this.setState(
[dbState]: this.props.userData[dbState]
);
);
callAttribute(field)
return <Field label =
field.label
key =
field.key
type =
field.type
name =
field.name
dbname =
field.dbName
component =
this.renderField
/>
onCroppedImgData(data)
this.setState(
croppedData: data
);
valueChange(e, dbName)
if (this.props.userData)
/**********Setting state dynamically here and called onChange method of textinput.And textinput value changed one character while we focused out.*********/
this.setState(
[dbName]: e.target.value
);
renderField(field)
const
meta:
touched,
error
= field;
const
label,
type,
key,
name,
dbname
= field;
if (label === "Upload Image")
let src;
if (this.props.userData)
src = this.props.userData[dbname];
return ( <
div className = "upload-image" >
<
UploadImage message = "Upload Image"
callbackImgCropped =
this.onCroppedImgData
profileImg =
src
/> <
/div>
)
else
let val;
if (this.props.userData)
console.log("=====this.state[dbname]===", this.state[dbname]);
val = this.state[dbname];
if (dbname === "dateOfJoin")
val = "";
return ( <
div className = "field-div" >
<
div >
<
span className = "label-name" >
label
< /span> <
input className = "form-input"
key =
key
type =
type
...field.input
ref =
name
value =
this.state[dbname]
onChange =
(e) =>
this.valueChange(e, dbname)
/> <
span className = "error-msg" >
touched ? error : ' '
< /span> <
/div> <
/div>
);
onSubmit(obj)
if (this.state.croppedData)
obj.croppedImage = this.state.croppedData;
if (this.props.userData)
obj.id = this.props.userData.id;
console.log("edit operation");
this.props.editEmployee(obj, (data) =>
this.props.reset();
);
else
if (this.state.croppedData)
obj.croppedImage = this.state.croppedData;
this.props.addEmployee(obj, (data) =>
this.setState(
createdUser: true
);
this.props.reset();
);
render()
const
handleSubmit,
pristine,
reset,
submitting
= this.props;
if (this.state.createdUser)
return ( < Redirect to = "/" / > );
else
return ( <
div className = "form-div" >
<
div className = "form-header" >
this.state.header
< /div> <
form className = "employee-form"
onSubmit =
handleSubmit(this.onSubmit.bind(this))
>
_.map(FIELDS, this.callAttribute.bind(this))
<
div className = "form-button" >
<
button type = "submit"
disabled =
submitting
>
Submit <
/button> <
button type = "button"
disabled =
pristine || submitting
onClick =
reset
>
Clear Values <
/button> <
/div> <
/form> <
/div>
);
function validate(values)
const errors = ;
_.each(FIELDS, (type, field) =>
if (!values[field] && type.type != "blob" && type.label != "Date Of Join")
if (type.type == "email")
errors[field] = `Enter an $field`;
else
errors[field] = `Enter a $field`;
else if (type.type == "email" && values[field])
if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]2,4$/i.test(values[field]))
errors[field] = 'Invalid email address'
else if (type.name == "reenterpassword" && values[field] !== values['password'])
errors[field] = 'Password mismatched.Please reenter password.';
);
return errors;
export default reduxForm(
validate,
fields: _.keys(FIELDS),
form: 'PostNewForm'
)(connect(null,
addEmployee,
editEmployee
)(PostNew));
【问题讨论】:
【参考方案1】: Yes got the solution ...We need to include "change" method from 'redux-form' and we need to dispatch the method with 3 arguments.
this.props.dispatch(change('PostNewForm', [dbName], e.currentTarget.value));
1st argument = form name
2nd argument = state name
3rd argument = value
Below is the working code...These redux form controls are uncontrolled .so we need to include change from redux-form.
import React, Component from 'react';
import ReactDOM from 'react-dom';
import Field, reduxForm,change from 'redux-form';
import _ from 'lodash';
import addEmployee from '../actions/employeeAction';
import editEmployee from '../actions/employeeAction';
import connect from 'react-redux';
import UploadImage from './uploadimage/uploadImage';
import Redirect from 'react-router-dom';
import Init from './index';
const FIELDS =
firstname:
type:'input',
label:'First Name',
key:1,
name:'firstname',
dbName:'firstname'
,
lastname:
type:'input',
label:'Last Name',
key:2,
name:'lastname',
dbName:'lastname'
,
password:
type:'password',
label:'Password',
key:3,
name:'password',
dbName:'password'
,
reenterpassword:
type:'password',
label:'Re-password',
key:4,
name:'reenterpassword',
dbName:'reenterpassword'
,
age:
type:'Number',
label:'Age',
key:5,
name:'age',
dbName:'age'
,
occupation:
type:'input',
label:'Occupation',
key:6,
name:'occupation',
dbName:'occupation'
,
city:
type:'input',
label:'City',
key:7,
name:'city',
dbName:'city'
,
state:
type:'input',
label:'State',
key:8,
name:'state',
dbName:'state'
,
pin:
type:'input',
label:'Pin',
key:9,
name:'pin',
dbName:'pin'
,
phone:
type:'input',
label:'Phone',
key:10,
name:'phone',
dbName:'phone'
,
email:
type:'email',
label:'Email',
key:11,
name:'email',
dbName:'email'
,
dateOfJoin:
type:'date',
label:'Date Of Join',
key:12,
name:'dateOfJoin',
dbName:'dateOfJoin'
,
uploadPhoto:
type:'blob',
label:'Upload Image',
key:13,
name:'uploadPhoto',
dbName:'croppedImage'
class PostNew extends Component
constructor()
super();
this.renderField = this.renderField.bind(this);
this.onCroppedImgData = this.onCroppedImgData.bind(this);
this.valueChange = this.valueChange.bind(this);
var stateData = [];
var constructState='"croppedData":"undefined","header":"Registration Form","createdEditUser":false';
_.each(FIELDS,(type,field)=>
let dbState = type.dbName;
constructState = constructState+',"'+dbState+'":""';
);
constructState = constructState + '';
this.state = JSON.parse(constructState);
componentWillMount()
if(this.props.header)
this.setState(header:this.props.header);
if(this.props.userData)
_.each(FIELDS,(type,field)=>
let dbState = type.dbName;
this.setState([dbState]:this.props.userData[dbState]);
);
callAttribute(field)
return <Field label=field.label key=field.key type=field.type name=field.name dbname=field.dbName component=this.renderField />
onCroppedImgData(data)
this.setState(croppedData:data);
valueChange(e,dbName)
this.setState([dbName]:e.currentTarget.value);
this.props.dispatch(change('PostNewForm', [dbName], e.currentTarget.value));
renderField(field)
const meta:touched,error = field;
const label,type,key,name,dbname = field;
if(label === "Upload Image")
let src;
if(this.props.userData)
src = this.props.userData[dbname];
return(
<div className="upload-image">
<UploadImage message="Upload Image" callbackImgCropped=this.onCroppedImgData profileImg=src/>
</div>
)
else
let val;
let placeholder = 'Please enter your '+label;
if(this.props.userData)
val = this.state[dbname];
if(dbname === "dateOfJoin")
val = "";
console.log("=====this.state[dbname]===",this.state[dbname]);
return(
<div className="field-div">
<div >
<span className="label-name">label</span>
<input className="form-input" key=key type=type ...field.input ref=name value=this.state[dbname] onChange=(e) => this.valueChange(e,dbname) placeholder=placeholder/>
<span className="error-msg">touched ? error : ' '</span>
</div>
</div>
);
onSubmit(obj)
if(this.state.croppedData)
obj.croppedImage = this.state.croppedData;
if(this.props.userData)
obj.id = this.props.userData.id;
console.log("edit operation");
this.props.editEmployee(obj,(data) =>
this.setState(createdEditUser:data.status);
this.props.reset();
);
else
if(this.state.croppedData)
obj.croppedImage = this.state.croppedData;
this.props.addEmployee(obj,(data) =>
this.setState(createdEditUser:true);
this.props.reset();
);
render()
const handleSubmit, pristine, reset, submitting = this.props;
if(this.state.createdEditUser)
return( <Redirect to="/signin" /> );
else
return(
<div className="form-div">
<div className="form-header">this.state.header</div>
<form className="employee-form" onSubmit=handleSubmit(this.onSubmit.bind(this))>
_.map(FIELDS,this.callAttribute.bind(this))
<div className="form-button">
<button type="submit" disabled=submitting>
Submit
</button>
<button type="button" disabled=pristine || submitting onClick=reset>
Clear Values
</button>
</div>
</form>
</div>
);
function validate(values)
const errors = ;
_.each(FIELDS,(type,field)=>
if(!values[field] && type.type != "blob" && type.label !="Date Of Join")
if(type.type == "email")
errors[field] = `Enter an $field`;
else
errors[field] = `Enter a $field`;
else if(type.type == "email" && values[field])
if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]2,4$/i.test(values[field]))
errors[field] = 'Invalid email address'
else if(type.name == "reenterpassword" && values[field]!==values['password'])
errors[field] = 'Password mismatched.Please reenter password.';
);
return errors;
export default reduxForm(
validate,
fields : _.keys(FIELDS),
form:'PostNewForm'
)(connect(null,addEmployee,editEmployee)(PostNew));
【讨论】:
以上是关于无法编辑文本输入反应 redux 表单的主要内容,如果未能解决你的问题,请参考以下文章