How get values from a select/option field in redux-form? - reactjs

I am trying to get the values from my second form. It renders some select options and when I hit the delete button it just returns an empty object. How do I get the value from the options. With the normal input fields it would pass values with the name.
For example if I had an input type="text" name="email", when I would submit this it would give my an object like:
{email: "some string"}
Here is the code:
import React , { Component } from 'react';
// import * as actions from '../actions';
import { reduxForm, Field } from 'redux-form';
import {connect} from 'react-redux';
import {postBooks, deleteBook} from '../../actions/booksActions';
class BooksForm extends Component {
renderField(field) {
const { meta: {touched, error} } = field;
const className = `form-group ${touched && error ? 'has-danger' : ''}`;
return (
<div className={className}>
<label className="control-label"><strong>{field.label}:</strong></label>
<input
className="form-control"
type={field.type}
{...field.input}
/>
<div className="text-help">
{ touched ? error : ''}
</div>
</div>
);
}
renderSelectField(field) {
const bookList = _.map(field.options, (book) => {
return (
<option key={book._id}>{book.title}</option>
)
});
return(
<div className="form-group">
<label htmlFor="sel1" className="control-label">{field.label}</label>
<select className="form-control" id="sel1">
{bookList}
</select>
</div>
);
}
onSubmit(values) {
this.props.postBooks(values);
}
onDelete(values) {
console.log(values);
}
render() {
const {handleSubmit} = this.props;
return (
<div>
<div className="well">
<form className="panel" onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<div className="panel-body">
<Field
label="Title"
name="title"
type="text"
component={this.renderField}
/>
<Field
label="Description"
name="description"
type="text"
component={this.renderField}
/>
<Field
label="Price"
name="price"
type="text"
component={this.renderField}
/>
<button className="btn btn-primary">Save Book</button>
</div>
</form>
</div>
<form className="Panel" onSubmit={handleSubmit(this.onDelete.bind(this))}>
<div className="panel-body">
<Field
label="Select Book"
name="selectedBook"
options={this.props.books}
component={this.renderSelectField}
/>
<button className="btn btn-danger">Delete</button>
</div>
</form>
</div>
);
}
}
function validate(values) {
const errors = {};
return errors;
}
function mapStateToProps(state) {
return {
books: state.books
}
}
export default reduxForm({
validate,
form: 'bookForm'
})(connect(mapStateToProps, {postBooks, deleteBook})(BooksForm));

In renderSelectField I needed to add {...field.input} into the select to allow redux-form to monitor it.
<select className="form-control" id="sel1" {...field.input}>

Related

Attempts to access this ref will fail. Did you mean to use React.forwardRef()?

I'm trying to create a sign up form with an input for a users address. The address input uses the google autocomplete address api.
I'd like to be able to keep it as a Formik field, so I can use Yup validation on it.
The address input component looks like
// Google.jsx
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
/* global google */
class SearchBar extends React.Component {
constructor(props) {
super(props);
this.autocompleteInput = React.createRef();
this.autocomplete = null;
this.handlePlaceChanged = this.handlePlaceChanged.bind(this);
}
componentDidMount() {
this.autocomplete = new google.maps.places.Autocomplete(this.autocompleteInput.current,
{"types": ["address"]});
this.autocomplete.addListener('place_changed', this.handlePlaceChanged);
}
handlePlaceChanged(){
const place = this.autocomplete.getPlace();
console.log(place);
}
render() {
return (
<Field ref={this.autocompleteInput} id="autocomplete" type="text" name="address" placeholder="" />
);
}
}
export default SearchBar;
And my Form component looks like:
import React from "react";
import { Formik, Form, Field, ErrorMessage } from "formik";
import * as Yup from "yup";
import SearchBar from "./Google";
const LoginSchema = Yup.object().shape({
fName: Yup.string().required("Please enter your first name"),
address: Yup.string().required("invalid address"),
});
class Basic extends React.Component {
render() {
return (
<div className="container">
<div className="row">
<div className="col-lg-12">
<Formik
initialValues={{
fName: "",
postal: "",
}}
validationSchema={LoginSchema}
onSubmit={(values) => {
console.log(values);
console.log("form submitted");
}}
>
{({ touched, errors, isSubmitting, values }) =>
!isSubmitting ? (
<div>
<div className="row mb-5">
<div className="col-lg-12 text-center">
<h1 className="mt-5">LoKnow Form</h1>
</div>
</div>
<Form>
<div className="form-group">
<label htmlFor="fName">First Name</label>
<Field
type="text"
name="fName"
className={`mt-2 form-control
${touched.fName && errors.fName ? "is-invalid" : ""}`}
/>
<ErrorMessage
component="div"
name="fName"
className="invalid-feedback"
/>
</div>
<div className="form-group">
<label htmlFor="address">Address</label>
<Field name="address" component={SearchBar} placeholder="" />
<ErrorMessage
component="div"
name="address"
className="invalid-feedback"
/>
</div>
<button
type="submit"
className="btn btn-primary btn-block mt-4"
>
Submit
</button>
</Form>
</div>
) : (
<div>
<h1 className="p-3 mt-5">Form Submitted</h1>
<div className="alert alert-success mt-3">
Thank for your connecting with us.
</div>
</div>
)
}
</Formik>
</div>
</div>
</div>
);
}
}
export default Basic;
This returns an error of "Function components cannot be given refs. Attempts to access this ref will fail. Did you mean to use React.forwardRef()?".
Which is coming from my address input component at:
<Field ref={this.autocompleteInput} id="autocomplete" type="text" name="address" placeholder="" />
Everything else is working, I just need to get past this last hurdle and I'll be good from here.
I will begin looking into the docs, but I'm unfortunately in a rush to get this done so I figured I'd try my luck here!
Any help is greatly appreciated! Thank you!

React-Redux How can I display the checkbox values?

I am trying to display the checkbox values but it is not showing anything on screen. Whatever values are selected from the checkbox are returning true in the console. How can I display the values that are selected. I am using redux forms. Even I want the values to be displayed in a comma seperated way. How can I achieve this? Thanks in advance.
Here's the code :
AddUser.js
import React, { Component } from 'react'
import { Field, reduxForm } from 'redux-form'
import { connect } from 'react-redux'
import { addUser } from '../../actions'
import './AddUser.css'
class AddUser extends Component {
renderInput(formProps) {
return (
<div>
<label>{formProps.label}</label>
<input {...formProps.input} type={formProps.type} max={formProps.max} autoComplete='off'
label={formProps.label} id={formProps.id}/>
{formProps.meta.touched &&
(formProps.meta.error && <span>{formProps.meta.error}</span>) }
</div>
)
}
onSubmit = (formValues) => {
console.log('formValues', formValues)
this.props.addUser(formValues)
}
render() {
const { handleSubmit } = this.props
const current = new Date().toISOString().split("T")[0]
return (
<div className='container wrapper'>
<form onSubmit={handleSubmit(this.onSubmit)}
className='form'>
<div>
<label>FullName</label>
<Field name='fullname' component={this.renderInput}
type='text' />
</div>
<div>
<label>Address</label>
<Field name='address' component={this.renderInput}
type='text' />
</div>
<div>
<label>BirthDate</label>
<Field name='birthdate' component={this.renderInput}
type='date'
max={current} />
</div>
<div>
<label>Select Your Gender</label>
<Field name='gender' component={this.renderInput} type='radio' value='male'
label='Male' />{' '}
<Field name='gender' component={this.renderInput} type='radio' value='female'
label='Female'/>{' '}
<Field name='gender' component={this.renderInput} type='radio' value='other'
label='Other' />{' '}
</div>
<div>
<label >Select Your Hobbies</label>
<Field name='travelling' component={this.renderInput} type='checkbox' value='travelling'
label='Travelling' />
<Field name='reading' component={this.renderInput} type='checkbox' value='reading'
label='Reading' />
<Field name='gaming' component={this.renderInput} type='checkbox' value='gaming'
label='Gaming' />
<Field name='doodling' component={this.renderInput} type='checkbox' value='doodling'
label='Doodling' />
</div>
<button type='submit'>Submit</button>
</form>
</div>
)
}
}
const validate = (formValues) => {
const errors = {}
if (!formValues.fullname) {
errors.fullname = 'You must enter a fullname'
}
if (!formValues.address) {
errors.address = 'You must enter the address'
}
if(!formValues.birthdate){
errors.birthdate='Please select your date of birth'
}
if(!formValues.gender){
errors.gender='Please select your gender'
}
return errors
}
export default connect(null, {
addUser: addUser
})(reduxForm({
form: 'adduser',
validate: validate
})(AddUser))
UsersList.js
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {listAllUsers} from '../../actions'
class ListUsers extends Component {
componentDidMount(){
this.props.listAllUsers()
}
usersList(){
return this.props.users.map((user)=>{
return (
<div key={user.id}>
<div>{user.fullname}</div>
<div>{user.address}</div>
<div>{user.birthdate}</div>
<div>{user.gender}</div>
<div>{user.hobbies}</div>
<div>
<button>Edit</button>
</div>
<div>
<button>Delete</button>
</div>
</div>
)
})
}
render() {
return (
<div>
<h1>Users List</h1>
{this.usersList()}
</div>
)
}
}
const mapStateToProps=(state)=>{
console.log(state)
return {users:state.users}
}
export default connect(mapStateToProps,{listAllUsers:listAllUsers})(ListUsers)
I'll show you an example for showing checkbox value in 1 line, you should be able do it on your own case.
function App() {
const [selectedInput, setSelectedInput] = React.useState([]);
const renderSelected = (e) => {
const targtValue = e.currentTarget.value;
setSelectedInput((prev)=>
prev.some(data => data === targtValue ) ?
prev.filter(data => data !== targtValue ) :
[...prev, targtValue]
)
}
return (
<div>
<label >Select Your Hobbies:</label><br/>
<p>{selectedInput.map(data=>data+",")}</p>
<label>Travelling
<input name='travelling' onChange={renderSelected} type='checkbox' value='travelling'/></label>
<label>Reading
<input name='reading' onChange={renderSelected} type='checkbox' value='reading'/></label>
<label>Gaming
<input name='gaming' onChange={renderSelected} type='checkbox' value='gaming' /></label>
<label>Doodling
<input name='doodling' onChange={renderSelected} type='checkbox' value='doodling'/></label>
</div>
);
}
ReactDOM.render(
<App/>,
document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>

React : TypeError: this.props.users.map is not a function

When I am adding a user and on submitting the user details it is redirecting back to the '/' route(which should display the users with their details) with an error. I've tried checking if the user is present then only do the mapping but it is not working. Can someone please help me to solve this, so that when I redirect back it should display the user that is added. The '/' route displays the List Users Page.
Here's the code:
UserForm.js
import React, { Component } from 'react'
import { Field, reduxForm } from 'redux-form'
import { connect } from 'react-redux'
import axios from 'axios'
import Checkbox from './Checkbox'
class UserForm extends Component {
renderInput(formProps) {
const className = `field ${formProps.meta.error && formProps.meta.touched ?
'error' : ''}`
return (
<div className={className}>
<label>{formProps.label}</label>
<input {...formProps.input} type={formProps.type} max={formProps.max} autoComplete='off'
label={formProps.label} id={formProps.id}
checked={formProps.input.value} />
{formProps.meta.touched &&
(formProps.meta.error && <span>{formProps.meta.error}</span>)}
</div>
)
}
onSubmit = (formValues) => {
console.log('formValues', formValues)
this.props.onSubmit(formValues)
}
render() {
const { handleSubmit } = this.props
const current = new Date().toISOString().split("T")[0]
let optionsList = [{ id: 1, name: 'Travelling' }, { id: 2, name: 'Reading' }, { id: 3, name: 'Gaming' }]
const colleges=['Pune University','S.P.College','F.C College']
return (
<div className='container'>
<form onSubmit={handleSubmit(this.onSubmit)}
className='ui form error'>
<div className='row mb-3'>
<label className='col-sm-2 col-form-label'>FullName</label>
<div className='col-sm-10'>
<Field name='fullname' component={this.renderInput}
type='text' className='form-control' />
</div>
</div>
<div className='row mb-3'>
<label className='col-sm-2 col-form-label'>Address</label>
<div className='col-sm-10'>
<Field name='address' component={this.renderInput}
type='text' />
</div>
</div>
<div className='row mb-3'>
<label className='col-sm-2 col-form-label'>BirthDate</label>
<div className='col-sm-10'>
<Field name='birthdate' component={this.renderInput}
type='date'
max={current} />
</div>
</div>
<div className='row mb-3'>
<label className='col-sm-2 col-form-label'>Select Your Gender</label>
<div className='col-sm-10 ui radio'>
<div className='form-check'>
<label className='form-check-label'>Male</label>
<Field name='gender' component='input' type='radio' value='male'
className='ui input' />{' '}
</div>
<div className='form-check'>
<label className='form-check-label'>Female</label>
<Field name='gender' component='input' type='radio' value='female'
/>{' '}
</div>
<div className='form-check'>
<label className='form-check-label'>Other</label>
<Field name='gender' component='input' type='radio' value='other'
/>{' '}
</div>
</div>
</div>
<div className='row mb-3'>
<label className='col-sm-2 '>Select Your Hobbies</label>
<div className='col-sm-10 ui checkbox'>
<Field name='roles' component={Checkbox} options={optionsList} type='checkbox' />
</div>
</div>
<div className='row mb-3'>
<label className='col-sm-2 col-form-label'>Select College</label>
<div className='col-sm-10'>
<Field name='college' component='select'>
<option value="">Select a college</option>
{colleges.map(collegeOption => (
<option value={collegeOption} key={collegeOption}>
{collegeOption}
</option>
))}
</Field>
</div>
</div>
<button type='submit' className='ui button'>Submit</button>
</form>
</div>
)
}
}
const validate = (formValues) => {
const errors = {}
if (!formValues.fullname) {
errors.fullname = 'You must enter a fullname'
}
if (!formValues.address) {
errors.address = 'You must enter the address'
}
if (!formValues.birthdate) {
errors.birthdate = 'Please select your date of birth'
}
if (!formValues.gender) {
errors.gender = 'Please select your gender'
}
if(!formValues.college){
errors.college='Please select your college'
}
return errors
}
export default reduxForm({
form: 'userform',
validate: validate
})(UserForm)
AddUser.js
import React, { Component } from 'react'
import { connect } from 'react-redux'
import { addUser } from '../../actions'
import UserForm from './UserForm'
class AddUser extends Component {
onSubmit = (formValues) => {
console.log('formValues', formValues)
this.props.addUser(formValues)
}
render() {
return(
<>
<div>Add User</div>
<UserForm onSubmit={this.onSubmit}/>
</>
)
}
}
export default connect(null, {
addUser: addUser
})(AddUser)
ListUsers.js
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {listAllUsers} from '../../actions'
import {Link} from 'react-router-dom'
class ListUsers extends Component {
componentDidMount(){
this.props.listAllUsers()
}
usersList(){
return this.props.users && this.props.users.map((user)=>{
return (
<div key={user.id}>
<div>{user.fullname}</div>
<div>{user.address}</div>
<div>{user.birthdate}</div>
<div>{user.gender}</div>
<div>{user.hobbies}</div>
<div>{user.college}</div>
<div>{user.roles}</div>
<div>
<Link to={`/users/edituser/${user.id}`} className='ui button secondary'>Edit</Link>
</div>
<div>
<Link to={`/users/deleteuser/${user.id}`} className='ui button negative'>Delete</Link>
</div>
</div>
)
})
}
render() {
return (
<div>
<Link to='/users/adduser' >Add User</Link>
<h1>Users List</h1>
{this.usersList()}
</div>
)
}
}
const mapStateToProps=(state)=>{
console.log(state)
return {users:state.users}
}
export default connect(mapStateToProps,{listAllUsers:listAllUsers})(ListUsers)
The map() function is available on arrays and it looks like users is not one. Check the type of users and ensure that it's an array.

Unable to type in input after adding value in React Js

I have tried with the following code with react js
import React, { Component } from 'react';
import Sidebar from './../Sidebar';
import Header from './../Header';
import {get_profile} from './../services/Services';
import $ from 'jquery';
export default class Profile extends Component {
constructor(props) {
super(props);
this.state = { userDetails: '' } ;
}
componentWillMount() {
$(window).scrollTop(0)
console.log('sdfds')
get_profile().then((response) => {
var userResults = $.parseJSON(response.text);
this.setState({ userDetails: userResults.response });
console.log(userResults);
}).catch((error) => {
//alert(error)
console.log(error);
});
}
handleChange(event) {
console.log(event.target.id)
this.setState({[event.target.name]: event.target.value});
}
render() {
return (
<div className="admin-panel">
<Sidebar />
<Header />
<div className="main-content">
<div className="contents">
<div className="container-fluid">
<div className="row">
<div className="col-sm-6">
<h2 className="page-title">Profile</h2>
<div className="form-group">
<label >First Name</label>
<input type="text" id="firstName" className="form-control" value={this.state.userDetails.firstName} />
</div>
<div className="form-group">
<label >Last Name</label>
<input type="text" id="lastName" className="form-control" value={this.state.userDetails.lastName} />
</div>
<div className="form-group">
<label >Email</label>
<input type="text" id="email" name="email" className="form-control" value={this.state.userDetails.email} />
</div>
<button type="button" className="btn btn-squared btn-success margin-inline" onClick={(e)=> {this.profileUpdate()}}>Update</button>
</div>
</div>
</div>
</div>
</div>
</div>
);
}
}
After fetching the results i'm unable to edit the input box value. I have tried with defaultValue but that also not working for me. I'm struck with this issue, Kindly help me to solve the issue.
Just pass an onChange handler to the input which will update the value of the corresponding key of userDetails like this:
<input
...
value={this.state.userDetails.firstName}
onChange={this.onChange}
/>
onChange(e) {
this.setState((previousState) => {
const userDetails = previousState.userDetails
return { userDetails: {...userDetails, firstName: e.target.value} }
})
}
or you can write a common onChange function like this:
<input
...
value={this.state.userDetails.firstName}
onChange={(e) => {this.onChange(e.target.value, 'firstName')}}
/>
<input
...
value={this.state.userDetails.lastName}
onChange={(e) => {this.onChange(e.target.value, 'lastName')}}
/>
<input
...
value={this.state.userDetails.email}
onChange={(e) => {this.onChange(e.target.value, 'email')}}
/>
onChange(value, key) {
this.setState((previousState) => {
const userDetails = previousState.userDetails
return { userDetails: {...userDetails, [key]: value} }
})
}

Clicking Next button doesn't taking it to next page

import React from 'react';
import { Link } from 'react-router';
import { Field } from 'redux-form';
import BaseForm from '..//BaseForm';
export default class XXXXXXX extends BaseForm {
componentWillMount() {
this.props.retrieveAcademies();
}
render() {
const {
handleSubmit,
formatGraduationDate,
pristine,
submitting,
infoError,
acadamyId
} = this.props;
return (
<div className="col-md-8 col-lg-8 mscs-text">
<div>
<h1 className="mscs-head">Self Registration </h1> <hr />
<form onSubmit={handleSubmit(this.props.startRegistrationProcess.bind(this))} className="registration-step1Class">
<div className="form-section">
<label htmlFor="firstName">First Name:</label>
<Field name="firstName" component={this.renderInputield} label="Enter first Name:" />
</div>
<div className="form-section">
<label htmlFor="lastName">Last Name:</label>
<Field name="lastName" component={this.renderInputield} label="Enter last Name:" />
</div>
<div id="datetimepicker2" className="form-section">
<label htmlFor="dob">Date of Birth:</label>
<Field name="dob" component={this.renderReactDatePicker} type="text" />
</div>
<div className="form-section">
<label htmlFor="maritimeAcadamy">Maritime Academy:</label>
{this.renderAcademiesSelection(acadamyId)}
</div>
<div className="form-section">
<label htmlFor="Yearpassed">Year Passed:</label>
<Field name="passedYear"
component={this.renderReactDatePicker}
type="text"
formatDate={formatGraduationDate}
/>
</div>
<br />
<div className="form-section">
<label htmlFor="CustomerNumber">Customer ID:</label>
<Field name="CustomerNumber" component={this.renderInputield} type="text" label="Enter Customer ID:" />
</div>
<div className="error validation-error">
{infoError && infoError.error} <br />
</div>
<input type="submit" className="btn btn-success" value="Next" />
<input type="reset" className="btn btn-default" value="Cancel" />
</form>
</div>
</div>
);
}
renderAcademiesSelection(acadamyId) {
return (
<div>
<select className="form-control" {...acadamyId}>
<option key={0} value={''}>{'Select your academy'}</option>
{
this.props.academies && this.props.academies.map(function (item, index) {
return (
<option key={item.Id} value={item.Id}>{item.Name}</option>
);
})
}
</select>
</div>
);
}
}
This is the component. Below is the container. The code has some textboxes and dropdowns and calendar controls.
Container :
function mapStateToProps(state, ownProps) {
return {
academies: state.academies.academies,
infoError: state.signUp.error
};
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
retrieveAcademies: () => {
dispatch(retrieveAcademies());
},
startRegistrationProcess: dispatchGenerateRegistrationToken.bind(this),
nextPage: ownProps.nextPage,
}
}
The above code samples are my react component and container. When I am clicking on the Next button it is not taking me to the next step and it is not showing any type of error in the console. I don't know where exactly the mistake is. I can't debug since the console is not giving any type of error. Any help is appreciated here.

Resources