React-Redux How can I display the checkbox values? - reactjs

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>

Related

React : TypeError : Cannot read property 'fullname' of undefined

When I try to submit the edited form it throws an error saying full name property value is undefined. I've passed the initial Values to the form when the form is in the edit mode. It displays the values when I visit the edit route but when I edit the values and submit , it throws an error. I am not getting what is wrong? I am using redux forms.
Here's the code :
UserForm.js
import React, { Component } from 'react'
import { Field, reduxForm } from 'redux-form'
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.onSubmit(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 reduxForm({
form: 'userform',
validate: validate
})(AddUser)
EditUser.js
import React, { Component } from 'react'
import {connect} from 'react-redux'
import {editUser} from '../../actions'
import UserForm from './UserForm'
class EditUser extends Component {
onSubmit=(formValues)=>{
this.props.editUser(this.props.match.params.id,formValues)
}
render() {
console.log('UserEdit',this.props)
if(!this.props.user){
<div>Loading...</div>
}
return (<>
<div>Edit User</div>
<UserForm onSubmit={this.onSubmit}
initialValues={{fullname:this.props.user.fullname,
address:this.props.user.address,
birthdate:this.props.user.birthdate,
gender:this.props.user.gender}}/>
</>
)
}
}
const mapStateToProps=(state,ownProps)=>{
return {user:state.users[ownProps.match.params.id]}
}
export default connect(mapStateToProps,{
editUser:editUser
})(EditUser)
actions/index.js
import {ADD_USER,USERS_LIST,EDIT_USER} from '../actions/types'
import users from '../apis/users'
import { v4 as uuid } from 'uuid'
import history from '../history'
export const addUser=(formValues)=>{
return async (dispatch)=>{
const userId=uuid()
const response=await users.post('/users',{...formValues,userId})
dispatch({
type:ADD_USER,
payload:response.data
})
history.push('/')
}
}
export const listAllUsers=()=>{
return async (dispatch)=>{
const response=await users.get('/users')
dispatch({
type:USERS_LIST,
payload:response.data
})
}
}
export const editUser=(id,formValues)=>{
return async (dispatch)=>{
const response=await users.patch(`/users/${id}`,formValues)
dispatch({
type:EDIT_USER,
payload:response.data
})
history.push('/')
}
}
reducers/userReducer.js
import {ADD_USER,USERS_LIST,EDIT_USER} from '../actions/types'
const userReducer=(state=[],action)=>{
switch(action.type){
case ADD_USER:
return [...state,action.payload]
case USERS_LIST:
return [...state,...action.payload]
case EDIT_USER:
const updatedUser=action.payload
const editedUser=state.map((user)=>{
if(user.id===updatedUser.id){
return updatedUser
}
return user
})
return {users:editedUser}
default:
return state
}
}
export default userReducer
can you try this..
return (<>
<div>Edit User</div>
{!!this.props.user &&
<UserForm onSubmit={this.onSubmit}
initialValues={{fullname:this.props.user.fullname,
address:this.props.user.address,
birthdate:this.props.user.birthdate,
gender:this.props.user.gender}}/>}
</>
)

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} }
})
}

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

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}>

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