I'm trying to create a login form that makes a API call who returns a token. I'm new with react and redux so to do that I followed this tutorial.
The login form is a redux-form. Here is the code :
login.js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Field, reduxForm } from 'redux-form';
import { loginUser } from '../../actions/index';
const form = reduxForm({
form: 'login'
});
class Login extends Component {
handleFormSubmit(formProps) {
this.props.loginUser(formProps);
}
renderAlert() {
if(this.props.errorMessage) {
return (
<div>
<span><strong>Error!</strong> {this.props.errorMessage}</span>
</div>
);
}
}
render() {
const { handleSubmit } = this.props;
return (
<div>
<form onSubmit={handleSubmit(this.handleFormSubmit.bind(this))}>
{this.renderAlert()}
{/* {this.renderAlert.bind(this)} */}
<div>
<label>Username</label>
<Field name="username" component="input" type="text" />
</div>
<div>
<label>Password</label>
<Field name="password" component="input" type="password" />
</div>
<button type="submit">Login</button>
</form>
</div>
);
}
}
function mapStateToProps(state) {
return {
errorMessage: state.auth.error,
message: state.auth.message
};
}
export default connect(mapStateToProps, { loginUser })(form(Login));
When the form is submitted, the props ({username, password}) are passed to HandleFormSubmit and then to loginUser function who is a redux action created to call the login API. That worked perfectly but now I'm trying to integrate Material Ui to stylised the fields of the form.
// input basic version
<Field name="username" component="input" type="text" />
// material-ui version
<Field name="username" component={TextField} type="text" />
With this change the props username and password are not passed to handleFormSubmit function so I can't realize a correct API call to login the user. So I need your help to fix this issue.
You need to introduce a translation layer from the props redux-form
provides to the material-ui
component. This is covered in the redux-form
docs here.
For a TextField
this would look like this:
const renderTextField = ({
input,
label,
meta: { touched, error },
...custom
}) => (
<TextField
hintText={label}
floatingLabelText={label}
errorText={touched && error}
{...input}
{...custom}
/>
)
Then you pass this as the component to the Field
:
<Field name="username" component={renderTextField} />
There is also a library that already has most of the wrappers you could need that you can just import
and use just as you did called redux-form-material-ui.