How to update the redux state using local state in a component - reactjs

I have a form in APP.js. upon submitting the form i need to display the data what i have entered in the form.In the reducer function , after dispatching the action in App.js i am trying to update the redux state . I have gone wrong here and stucked more than 2hrs. can anyone please help??
//App.js
import React,{Component} from 'react';
import {action1} from './Actions/action1'
import './App.css';
import {connect} from 'react-redux'
import Display from './Components/Display'
const mapDispatchToProps=(dispatch)=>{
return{
submitHandler:(details)=>dispatch(action1(details))
}
}
class App extends Component {
constructor(){
super();
this.state={
details: {FirstName:'', LastName:'', Age: ''}
}
}
nameHandler=(event)=>{
const details = this.state.details;
details[event.target.name]= event.target.value;
this.setState({details});
}
SubmitHandler=(event)=>{
event.preventDefault()
/*
const firstname=this.state.details.FirstName
const lastname=this.state.details.LastName
const age=this.state.details.Age
*/
this.props.submitHandler(this.state.details)
}
render(){
return (
<div className="App">
<form onSubmit={this.SubmitHandler}>
<div className="form-group">
<input
type="text"
placeholder="FirstName"
value={this.state.details.FirstName}
onChange={this.nameHandler}
className="form-control"
name="FirstName"
/>
</div>
<div className="form-group">
<input
type="text"
placeholder="LastName"
value={this.state.details.LastName}
onChange={this.nameHandler}
className="form-control"
name="LastName"
/>
</div>
<div className="form-group">
<input
type="text"
placeholder="Age"
value={this.state.details.Age}
onChange={this.nameHandler}
className="form-control"
name="Age"
/>
</div>
<div className="form-group">
<button type="submit" className="btn btn-primary">Submit Form</button>
</div>
</form>
<Display/>
</div>
);
}
}
//my action
import {SUBMISSION} from '../Constants/actiontypes'
export const action1=(body)=>{
console.log(body)
return{
type:SUBMISSION,
payload:body
}
}
//my reducer
import {SUBMISSION} from '../Constants/actiontypes'
const reducer1=(state=[],action)=>{
if(action.type===SUBMISSION){
return [...state,{firstname: action.payload.FirstName,lastname:action.payload.LastName,age:action.payload.Age}];
}
return state
}
export default reducer1
i can see what ever the values entered through action.payload but failed to update the state

return [...state,{firstname:
action.payload.FirstName,lastname:action.payload.LastName,age:action.payload.Age}];
You are returning an array make it object.
return {
...state,
firstname: action.payload.FirstName,
lastname: action.payload.LastName,
age:action.payload.Age
};

Related

No data passed in submit method of Redux-form

I want to send the input values to the api.
I used the code from below link, to get the input values in the submit method, but though the submit method gets called, the variable is empty.
How to handle redux form submitted data
index.js
import React from "react";
import ReactDOM from "react-dom";
import "./index.css";
import ContactForm from "./ContactForm";
import * as serviceWorker from "./serviceWorker";
import { createStore } from "redux";
import { Provider } from "react-redux";
import rootReducers from "./reducers";
const store = createStore(rootReducers);
ReactDOM.render(
<Provider store={store}>
<ContactForm />
</Provider>,
document.getElementById("root")
);
serviceWorker.unregister();
reducer.js
import { combineReducers } from "redux";
import { reducer as formReducer } from "redux-form";
const rootReducer = combineReducers({
form: formReducer
});
export default rootReducer;
ContactForm.js
import React, { Component } from "react";
import { reduxForm } from "redux-form";
class ContactForm extends Component {
submit(formValues) {
console.log(formValues);
}
render() {
const {
fields: { firstName, lastName, email },
handleSubmit
} = this.props;
return (
<form onSubmit={handleSubmit(this.submit)}>
<div>
<label>First Name</label>
<input type="text" placeholder="First Name" {...firstName} />
</div>
<div>
<label>Last Name</label>
<input type="text" placeholder="Last Name" {...lastName} />
</div>
<div>
<label>Email</label>
<input type="email" placeholder="Email" {...email} />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
ContactForm = reduxForm({
form: "contact",
fields: ["firstName", "lastName", "email"]
})(ContactForm);
export default ContactForm;
I am getting formValues as empty. Could anyone please help me with it?
It seems the example was for version 5.3.1 of Redux-form, while I had installed 8.1.0 version.
Below is the working code:
import React, { Component } from "react";
import { Field, reduxForm } from "redux-form";
const submit = values => {
console.log(values);
};
class ContactForm extends Component {
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(submit)}>
<div>
<label>First Name</label>
<Field name="firstName" component="input" type="text" />
</div>
<div>
<label>Last Name</label>
<Field name="lastName" component="input" type="text" />
</div>
<div>
<label>Email</label>
<Field name="email" component="input" type="email" />
</div>
<button type="submit">Submit</button>
</form>
);
}
}
export default reduxForm({
form: "contact"
})(ContactForm);
You probably need to use instead of inside the form, to connect your input data with redux store.
https://redux-form.com/8.3.0/examples/submitvalidation/

Why data is not rendered on refresh in react js with asynchronous call?

I am creating edit form.First i have to get data to edit form and i am calling it in componentDidMount().Please see code below.
import React from 'react';
import CompanyForm from './CompanyForm';
import { connect } from 'react-redux';
import { companyActions } from '../../../redux/actions/company-action';
class EditCompanyPage extends React.Component {
constructor(props){
super(props);
};
componentDidMount () {
const { id } = this.props.match.params
const { dispatch } = this.props;
dispatch(companyActions.getCompany(id));
}
render(){
const {editUser } = this.props;
return(
<div>
<h1>Edit Company</h1>
{
editUser && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
}
</div>
);
};
}
function mapStateToProps(state) {
const { editUser } = state.companyReducer;
return {
editUser
};
}
const EditCompany = connect(mapStateToProps)(EditCompanyPage);
export default EditCompany;
see code for CompanyForm component below:
import React from 'react';
class CompanyForm extends React.Component {
constructor(props){
super(props);
this.state = {
company :{
name : this.props.companyDataFP.name || '',
address1 : this.props.companyDataFP.address1 || '',
}
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
};
handleChange(e) {
const { name, value } = e.target;
const newState = Object.assign({}, this.state);
newState.company[name] = value;
this.setState(newState);
}
handleSubmit(e) {
e.preventDefault();
return false;
}
render(){
return(
<div className="col-md-12">
<form onSubmit={this.handleSubmit}>
<div className="row">
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="name">Name</label>
<input type="text" name="name" className="form-control" onChange={this.handleChange} value={this.state.company.name} />
</div>
</div>
<div className="col-md-6">
<div className='form-group'>
<label htmlFor="address1">Address 1</label>
<input type="text" name="address1" className="form-control" onChange={this.handleChange} value={this.state.company.address1} />
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className='form-group'>
<input type="submit" className="btn btn-info" value="submit" />
</div>
</div>
</div>
</form>
</div>
);
};
}
export default CompanyForm;
It works fine when i access this form with
<Link to="/edit-form/:id" >Edit</Link>
but when i refresh the current page then values are not rendering into form to edit.
I am using redux approach for state management, please guide me i am new to react.
Probably ComponyForm initializes form on its componentDidMount lifecycle function, so when editUser arrives nothing will change.
A way to handle this is changing:
<CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />
to:
{editUser.name && <CompanyForm handleActionParent={this.handleAction} companyDataFP={editUser} />}

Values with Redux-Form return null

im work with Redux and React, in CRUD operations with API , createPost return null into the values of title, categories, and content with Redux-Form?
I could help, I do not know what my mistake ?
actions file index.js
export const CREATE_POST = 'CREATE_POST';
const URL = 'http://reduxblog.herokuapp.com/api';
const API_KEY = '1234557';
export function createPost(props) {
const request = axios
.post(`${URL}/posts?${API_KEY}`, props)
.then( res => { console.log(res) })
return {
type: CREATE_POST,
payload: request,
};
}
component file newPost.js
import React from 'react';
import { reduxForm } from 'redux-form';
import {crearPost} from '../acciones/index';
import {connect} from 'react-redux';
class NuevoPost extends React.Component {
onSubmit(values) {
this.props.crearPost(values)
}
render() {
const {fields: {
title, categories, content} ,
handleSubmit } = this.props;
return (
<form onSubmit={
handleSubmit(this.onSubmit.bind(this))}>
<h3>Crea un nuevo Post.</h3>
<div className='form-group'>
<label
>titulo</label>
<input
type='text'
className='form-control'
{...title}
/>
</div>
<div className='form-group'>
<label
>Categoria</label>
<input
type='text'
className='form-control'
{...categories}
/>
</div>
<div className='form-group'>
<label
>Contenido</label>
<textarea
type='text'
className='form-control'
{...content}
/>
</div>
<button
type="submit"
className="btn btn-info"
>Postear</button>
</form>
)
}
}
export default reduxForm({
form: 'newPost',
fields: ['title', 'categories', 'content']
})(connect(null, { crearPost })(NuevoPost));
You need to use redux-form Field here
import { reduxForm, Field } from 'redux-form';
<div className='form-group'>
<label>Categoria</label>
<Field
type='text'
className='form-control'
component={'input'}
/>
</div>

REDUX-FORM error on handleSubmit

I am getting error while using redux-form
Error msg in console:
bundle.js:32511 Uncaught Error: You must either pass handleSubmit()
an onSubmit function or pass onSubmit as a prop(…)
the above error appeared on page load and button click
Please refer to the below code sample which cause the console error.
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
import { createPost } from '../actions/index';
class PostsNew extends Component {
render() {
const { fields: { title, categories, content }, handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.props.createPost)}>
<h3>Create a new Post</h3>
<div className="form-group">
<label>Title</label>
<input type="text" className="form-control" {...title}/>
</div>
<div className="form-group">
<label>Categories</label>
<input type="text" className="form-control" {...categories}/>
</div>
<div className="form-group">
<label>Content</label>
<textarea className="form-control" {...content}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
);
}
}
export default reduxForm({
form: 'PostsNewForm',
fields: ['title', 'categories', 'content']
}, null, { createPost })(PostsNew);
This was a step by step follow of StephenGrider redux tutorial
Thanks in advance :)
If PostsNew is Container (if this is directly invoked form Routes) then you have to make handleSubmit function instead of taking from this.props
import React, { Component } from 'react';
import { reduxForm } from 'redux-form';
import { createPost } from '../actions/index';
class PostsNew extends Component {
handleSubmit(formValues){
console.log(formValues);
//do what ever you want
}
render() {
const { fields: { title, categories, content } } = this.props;
return (
<form onSubmit={this.handleSubmit(this.props.createPost)}>
<h3>Create a new Post</h3>
<div className="form-group">
<label>Title</label>
<input type="text" className="form-control" {...title}/>
</div>
<div className="form-group">
<label>Categories</label>
<input type="text" className="form-control" {...categories}/>
</div>
<div className="form-group">
<label>Content</label>
<textarea className="form-control" {...content}/>
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
);
}
}
OR
In case PostsNew is React Component that is used inside a Container then you can pass handleSubmit in props of PostsNew
<PostsNew
handleSubmit={ (values) => {console.log(values)}}
/>
You need to pass onsubmit props from parent component
import React from 'react';
import { connect } from 'react-redux';
import { initialize } from 'redux-form';
import PostsNew from './PostsNew';
class App extends React.Component {
handleSubmit(data) {
console.log('Submission received!', data);
this.props.dispatch(initialize('contact', {})); // clear form
}
render() {
return (
<div id="app">
<h1>App</h1>
<PostsNew onSubmit={this.handleSubmit.bind(this)}/>
</div>
);
}
}
export default connect()(App);
I was running into the same problem until I explicitly imported connect into my file. After that, I was able to call this.props.createPost successfully.
This is my solution:
import React, { Component } from 'react';
import { Field, reduxForm } from 'redux-form'
import { createPost } from '../actions/index';
import { connect } from 'react-redux';
class PostsNew extends Component {
render() {
const { handleSubmit } = this.props;
return (
<form onSubmit={handleSubmit(this.props.createPost)}>
<h3>Create a New Post</h3>
<div className="form-group">
<label>Title</label>
<Field name="title" component="input" type="text" className="form-control" placeholder="Title" />
</div>
<div className="form-group">
<label>Categories</label>
<Field name="categories" component="input" type="text" className="form-control" placeholder="Title" />
</div>
<div className="form-group">
<label>Content</label>
<Field name="content" component="textarea" type="text" className="form-control" placeholder="Title" />
</div>
<button type="submit" className="btn btn-primary">Submit</button>
</form>
);
}
}
export default connect(null, {createPost})(reduxForm({
form: 'PostsNew'
})(PostsNew));
This works perfectly. Check your action creator there should be a typo error in your action creator. Please refer the below action creator. If you followed the steps as he mentioned, this should work perfectly. What the error says is you don't have something called createPost in your props. Further more you can find my working project here in github.
export function createPost(props) {
console.log(props);
const request = axios.post(`${ROOT_URL}/posts${API_KEY}`, props);
return {
type: CREATE_POST,
payload: request
};
}
please install version 5 of redux-form.
npm install --save redux-form#5

Redux-form : get information from a custom form with interlock components

I m using redux-form from : http://redux-form.com/4.2.0 and I tried the simple contact form example, that you can see here :
import React, {Component} from 'react';
import {reduxForm} from 'redux-form';
import TitleBlock from './TitleBlock'
class ContactForm extends Component {
render() {
const {fields: {firstName, lastName, email}, handleSubmit} = this.props;
return (
<form onSubmit={handleSubmit}>
<div>
<label>First Name</label>
<input type="text" placeholder="First Name" {...firstName}/>
</div>
<div>
<label>Last Name</label>
<input type="text" placeholder="Last Name" {...lastName}/>
</div>
<div>
<label>Email</label>
<input type="email" placeholder="Email" {...email}/>
</div>
<TitleBlock />
<button type="submit">Submit</button>
</form>
);
}
}
ContactForm = reduxForm({ // <----- THIS IS THE IMPORTANT PART!
form: 'contact', // a unique name for this form
fields: ['firstName', 'lastName', 'email'] // all the fields in your form
})(ContactForm);
export default ContactForm;
It works very well, but I want to separate my component to create forms with custom blocks, for exemple I created a title block here :
import React, { Component, PropTypes } from 'react'
import {reduxForm} from 'redux-form';
export const fields = ['title', 'description'];
export default class TitleBlock extends Component {
static propTypes = {
fields: PropTypes.object.isRequired,
};
render() {
const {
fields: {title,description},
} = this.props;
return (
<div>
<div>
<label>Title</label>
<div>
<input type="text" placeholder="Title" {...title}/>
</div>
</div>
<div>
<label>Description</label>
<div>
<input type="text" placeholder="Description" {...description}/>
</div>
</div>
</div>
)
}
}
export default reduxForm({
form: 'TitleBlock',
fields
})(TitleBlock);
And I want to interlock this TitleBlock to my contact Form, is it possible to do that and manage all the informations in one single submit function ?
Instead of connecting TitleBlock to redux-form, you can have your ContactForm component pass the fields prop into TitleBlock like so:
class ContactForm extends React.Component {
...
render() {
return (
<div>
<TitleBlock fields={this.props.fields} />
...
</div>
);
}
}
export default reduxForm({...})(ContactForm)
And your TitleBlock component could look like this:
export default class TitleBlock extends Component {
static propTypes = {
fields: PropTypes.object.isRequired,
};
render() {
const { fields: { title, description } } = this.props;
return (
<div>
<div>
<label>Title</label>
<div>
<input type="text" placeholder="Title" {...title}/>
</div>
</div>
<div>
<label>Description</label>
<div>
<input type="text" placeholder="Description" {...description}/>
</div>
</div>
</div>
);
}
}

Resources