Reputation: 9194
Been fighting with this since yesterday, but this is as close to working as I can get. Just trying to pre-populate input fields with data received from server. Seems pretty simple, but I'm missing something apparently.
While I can get the fields to populate, it pretty much locks all the fields in the form from editing--ones that aren't pre-populated and should be editable.
This a snippet of what I have so far that kinda "works". The username is one where the server could respond with a value and if does it uses renderDisabledField
: it populates the field with the value
and disables it so it can't be edited. Otherwise, it should be editable. The password fields on the other hand should always be editable.
componentWillReceiveProps() {
this.props.initialize(this.props.acctVal);
}
renderField(field) {
const {
placeholder,
type,
name,
meta: {
touched,
error
}
} = field;
return (
<div className='form-group'>
<input
className='form-control'
type={type}
placeholder={placeholder}
{...field.input}
/>
<div className='text-danger'>
{touched ? error : ""}
</div>
</div>
);
}
renderDisabledField(field) {
const {
type,
name,
placeholder,
} = field;
return (
<div className='form-group'>
<input
className='form-control'
type={type}
placeholder={placeholder}
disabled
{...field.input}
/>
</div>
);
}
render() {
if (this.props.permitRender) {
const { handleSubmit } = this.props;
return (
<div>
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
{this.renderAlert()}
<h4>Set Username</h4>
<p>Please enter the username you would like associated with your account. It must be at least 5 characters in length.</p>
<Field
name='username'
type='text'
placeholder='Enter Username'
onBlur={this.validateUsername.bind(this)}
component={this.props.acctVal.username ? this.renderDisabledField : this.renderField}
/>
<hr />
<h4>Set New Password</h4>
<p>Type your new password twice. </p>
<p>It must be a minimum of 8 characters in length and contain at least:</p>
<ol>
<li>One uppercase character</li>
<li>One special character</li>
<li>One number</li>
</ol>
<Field
name='password1'
type='password'
placeholder='Enter New Password'
component={this.renderField}
/>
<Field
name='password2'
type='password'
placeholder='Confirm Password'
component={this.renderField}
/>
<hr />
<button type="submit" className="btn btn-primary">Submit</button>
</form>
<br />
</div>
);
} else if (!this.props.permitRender) {
return (
<Loading />
);
}
}
function mapStateToProps(state) {
return {
errorMessage: state.auth.error,
permitRender: state.auth.permitRender,
questions: state.auth.questions,
acctVal: state.auth.acctVal
};
}
SetupUser = reduxForm({
form: 'setup_user',
touchOnChange: true,
validate
})(SetupUser);
SetupUser = connect(mapStateToProps, { checkUsername, setupUser, verifyKey })(SetupUser);
export default SetupUser;
EDIT:
Almost forgot the reducer:
import {
ACCT_VALUES
} from '../actions/authentication';
export default function(state = {}, action) {
switch(action.type) {
case ACCT_VALUES:
return { ...state,
acctVal: {
username: action.payload.data.username,
company: action.payload.data.company_name[0].company_name,
firstname: action.payload.data.first_name,
lastname: action.payload.data.last_name,
email: action.payload.data.email,
phone: action.payload.data.phone
},
};
default:
return state;
}
return state;
}
I've tried the various rendering it at different points in the life cycle:
https://reactjs.org/docs/react-component.html#the-component-lifecycle
Also tried following these through but haven't been able to get the desired results:
https://redux-form.com/6.7.0/examples/initializefromstate/
How to properly set default values using redux-forms?
EDIT: Going in circles and retrying stuff I have already tried.
This works in getting a value into the field, but breaks when you try passing state
or props
into the initialValues
.
function mapStateToProps(state) {
return {
errorMessage: state.auth.error,
permitRender: state.auth.permitRender,
questions: state.auth.questions,
acctVal: state.auth.acctVal
};
}
SetupUser = reduxForm({
form: 'setup_user',
touchOnChange: true,
validate,
initialValues: {username: 'test1'}
}, mapStateToProps)(SetupUser);
SetupUser = connect(mapStateToProps, { checkUsername, setupUser, verifyKey })(SetupUser);
export default SetupUser;
Get the `Cannot read property 'props' of undefined with this and about a dozen other variations:
initialValues: this.props.acctVal
initialValues: {this.props.acctVal}
initialValues: {username: this.props.acctVal.username}
Upvotes: 0
Views: 559
Reputation: 9194
The things one assumes to be a minor detail that are imperative.
In this case, what I had labeled as acctVal
really should have been called initialValues
like the documentation says:
function mapStateToProps(state) {
return {
errorMessage: state.auth.error,
permitRender: state.auth.permitRender,
questions: state.auth.questions,
initialValues: state.auth.acctVal
};
}
SetupUser = reduxForm({
form: 'setup_user',
touchOnChange: true,
validate,
})(SetupUser);
SetupUser = connect(mapStateToProps, { checkUsername, setupUser, verifyKey })(SetupUser);
export default SetupUser;
Then just could get rid of the:
componentWillReceiveProps() {
this.props.initialize(this.props.acctVal);
}
Upvotes: 1