Reactjs: Using same form for add and update - reactjs

I crafted a reactjs crud app with help of a tutorial and it works great now. Now i am trying to merge two form together so that same form should be used for both add and update operation.
This is my allpost.js file
import React, { Component } from 'react';
import { connect } from 'react-redux';
import Post from '../components/Post';
import EditComponent from '../components/editComponent';
class AllPost extends Component {
render() {
return (
<div>
<h1>All Posts</h1>
{this.props.posts.map((post) => (
<div key={post.id}>
{post.editing ? <EditComponent post={post} key={post.id} /> :
<Post key={post.id} post={post} />}
</div>
))}
</div>
);
}
}
const mapStateToProps = (state) => {
return {
posts: state
}
}
export default connect(mapStateToProps)(AllPost);
and this is my postForm.js file:
import React, { Component } from 'react';
import { connect } from 'react-redux'
class PostForm extends Component {
handleSubmit = (e) => {
e.preventDefault();
const title = this.getTitle.value;
const message = this.getMessage.value;
const data = {
id: new Date(),
title,
message,
editing: false
}
console.log(data)
this.props.dispatch({
type: 'ADD_POST',
data,
});
this.getTitle.value = '';
this.getMessage.value = '';
}
render() {
return (
<div>
<h1>Create Post</h1>
<form onSubmit={this.handleSubmit}>
<input required type="text" ref={(input)=>this.getTitle = input}
placeholder="Enter Post Title"/>
<br /><br />
<textarea required rows="5" ref={(input)=>this.getMessage = input} cols="28"
placeholder="Enter Post" />
<br /><br />
<button>Post</button>
</form>
</div>
);
}
}
export default connect()(PostForm);
and this is my editComponent.js file
import React, { Component } from 'react';
import { connect } from 'react-redux';
class EditComponent extends Component {
handleEdit = (e) => {
e.preventDefault();
const newTitle = this.getTitle.value;
const newMessage = this.getMessage.value;
const data = {
newTitle,
newMessage
}
this.props.dispatch({ type: 'UPDATE', id: this.props.post.id, data: data })
}
render() {
return (
<div>
<form onSubmit={this.handleEdit}>
<input required type="text" ref={(input) => this.getTitle = input}
defaultValue={this.props.post.title} placeholder="Enter Post Title" /><br /><br />
<textarea required rows="5" ref={(input) => this.getMessage = input}
defaultValue={this.props.post.message} cols="28" placeholder="Enter Post" /><br /><br />
<button>Update</button>
</form>
</div>
);
}
}
export default connect()(EditComponent);
and this is my post.js file:
import React, { Component } from 'react';
import { connect } from 'react-redux'
class Post extends Component {
render() {
return (
<div>
<h2>{this.props.post.title}</h2>
<p>{this.props.post.message}</p>
<button onClick={() => this.props.dispatch({type: 'EDIT_POST', id: this.props.post.id})}>EDIT
</button>
<button onClick={ () => this.props.dispatch({type: 'DELETE_POST', id: this.props.post.id}) }>DELETE
</button>
</div>
);
}
}
export default connect()(Post);
and this is my postReducer.js file:
const postReducer = (state = [], action) => {
switch(action.type) {
case 'ADD_POST':
return state.concat([action.data]);
case 'DELETE_POST':
return state.filter((post)=>post.id !== action.id);
case 'EDIT_POST':
return state.map((post)=>post.id === action.id ? {...post,editing:!post.editing}:post)
case 'UPDATE':
return state.map((post)=>{
if(post.id === action.id) {
return {
...post,
title:action.data.newTitle,
message:action.data.newMessage,
editing: !post.editing
}
} else return post;
})
default:
return state;
}
}
export default postReducer;
Can anyone please help me to achieve this? I tried a lot to use same form form for both add and update and i failed to achieve this.

I think it's better you create separate component for rendering form data(FormComponent) and separate components for edit(EditComponent) and add(AddComponent).
This way there will not be clutter in one component and no if/else conditions for different modes like edit or add, or in future copy mode.
This approach will add flexibility and enhances compositional pattern of react.
1) AddComponent
import React, { Component } from 'react';
import { connect } from 'react-redux'
class AddComponent extends Component {
handleSubmit = (title, message) => {
const data = {
id: new Date(),
title,
message,
editing: false
}
this.props.dispatch({
type: 'ADD_POST',
data,
});
}
render() {
return (
<div>
<h1>Create Post</h1>
<FormComponent
buttonLabel='Post'
handleSubmit={this.handleSubmit}
/>
</div>
);
}
}
export default connect()(AddComponent);
2) EditComponent
import React, { Component } from 'react';
import { connect } from 'react-redux';
class EditComponent extends Component {
handleSubmit = (newTitle, newMessage) => {
const data = {
newTitle,
newMessage
}
this.props.dispatch({ type: 'UPDATE', id: this.props.post.id, data: data })
}
render() {
return (
<div>
<FormComponent
buttonLabel='Update'
handleSubmit={this.handleSubmit}
/>
</div>
);
}
}
export default connect()(EditComponent);
3) FormComponent
import React, { Component } from 'react';
class FormComponent extends Component {
handleSubmit = (e) => {
e.preventDefault();
const title = this.getTitle.value;
const message = this.getMessage.value;
this.props.handleSubmit(title, message);
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<input required type="text" ref={(input) => this.getTitle = input}
defaultValue={this.props.post.title} placeholder="Enter Post Title" /><br /><br />
<textarea required rows="5" ref={(input) => this.getMessage = input}
defaultValue={this.props.post.message} cols="28" placeholder="Enter Post" /><br /><br />
<button>{this.props.buttonLabel}</button>
</form>
);
}
}
export default FormComponent;
Hope that helps!!!

You can create your own Form component with a prop of editMode to control whether it's Create or Update.
import React, {Component} from 'react';
import PropTypes from 'prop-types';
class Form extends Component {
handleSubmit = e => {
e.preventDefault();
const {editMode, post} = this.props;
const title = this.titleRef.value;
const body = this.bodyRef.value;
if (editMode){
const data = {
title,
body
}
this.props.dispatch({type: 'UPDATE', id: post.id, data})
}
else {
const data = {
id: new Date(),
title,
message,
editing: false
}
this.props.dispatch({type: 'ADD_POST', data});
}
}
render() {
const {editMode, post} = this.props;
const pageTitle = editMode ? 'Edit Post' : 'Create Post';
const buttonTitle = editMode ? 'Update' : 'Post';
return (
<div>
<h1>{pageTitle}</h1>
<form onSubmit={this.handleSubmit}>
<input
required
type="text"
ref={input => this.titleRef = input}
placeholder="Enter Post Title"
defaultValue={post.title}
/>
<textarea
required
rows="5"
ref={input => this.bodyRef = input}
cols="28"
placeholder="Enter Post"
defaultValue={post.body}
/>
<button>{buttonTitle}</button>
</form>
</div>
);
}
}
Form.propTypes = {
editMode: PropTypes.bool,
post: PropTypes.object
}
Form.defaultProps = {
editMode: false, // false: Create mode, true: Edit mode
post: {
title: "",
body: ""
} // Pass defined Post object in create mode in order not to get undefined objects in 'defaultValue's of inputs.
}
export default Form;
It would be on create mode by default but if you wanna update the post you should pass editMode={true} to your form component.

Related

Validation Message is not Showing in SimpleReactValidator library Reactjs

I want to add validation in my react form I am using SimpleReactValidator library for validation, but once I setup the code, the error is not displaying. But when i add
{validator.showMessages('fullName', fullName, 'required|alpha')}
before the return statement it's showing me without click on submit button.
Here's my code
import React, { useState } from 'react';
import SimpleReactValidator from 'simple-react-validator';
const UserDetails = ({ setForm, formData, navigation }) => {
const {
fullName
}= formData;
const useForceUpdate = () => useState()[1];
const validator = new SimpleReactValidator();
const forceUpdate = useForceUpdate();
const submitForm = (e) =>{
e.preventDefault()
if (validator.allValid()) {
alert('You submitted the form and stuff!');
} else {
validator.showMessages();
forceUpdate();
}
}
return(
<>
<input
type="text"
name="fullName"
placeholder='Name'
onChange={setForm}
defaultValue={fullName}
/>
{validator.message('fullName', fullName, 'required|alpha')}
</>
);
}
export default UserDetails;
Hope this will help you
import React, { useState } from 'react';
import SimpleReactValidator from 'simple-react-validator';
const UserDetails = () => {
const validator = new SimpleReactValidator();
const [state, setState] = useState({
fullName:""
})
const handleChnage = (e) => {
setState({
fullName:e.target.value
})
}
const submitForm = () => {
if (validator.allValid()) {
alert('You submitted the form and stuff!');
} else {
validator.showMessages();
}
}
return (
<>
<input
type="text"
name="fullName"
placeholder='Name'
onChange={(e) => handleChnage(e)}
defaultValue={state.fullName}
/>
{validator.message('fullName', state.fullName, 'required|alpha')}
<button onClick={() => submitForm()}>submit</button>
</>
);
}
export default UserDetails;
This code example would solve your problem.
class App extends React.Component {
constructor(props){
super(props)
this.validator = new SimpleReactValidator({autoForceUpdate: this});
this.state = {
fullName: ''
};
}
handleFullNameChange(e) {
this.setState({fullName: e.target.value});
}
handleFullNameBlur() {
if(this.validator.allValid()) {
this.validator.hideMessages();
} else {
this.validator.showMessages();
}
}
render(){
return (
<div>
<input type="text" name="fullName" placeholder='Name' onChange={this.handleFullNameChange.bind(this)} onBlur={this.handleFullNameBlur.bind(this)} value={this.state.fullName} />
{this.validator.message('fullName', this.state.fullName, 'required|alpha')}
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById('root'))
You can also take a look on Codepen here: https://codepen.io/aptarmy/pen/oNXRezg

React setState doesn't update the state after submitting input form

I am new in React and want to develop easy app - there is input field from which I want to take values and render list. After added option in text field I want to update this list whith new option.
setState function does not work and I don't know how to connect input submit and list rendering. My code is below.
WaterApp.js
import React from 'react';
import AddWater from './AddWater';
import WaterElements from './WaterElements';
export default class WaterApp extends React.Component {
state = {
quantities: ['aaaaa', 'bbbbb', 'ccccc']
};
handleAddQuantity = (quantity) => {
this.setState(() => ({
quantities: ['ddddd', 'eeeee']
}));
console.log('works');
}
render() {
return (
<div>
<WaterElements quantities={this.state.quantities} />
<AddWater handleAddQuantity={this.handleAddQuantity} />
</div>
)
}
}
AddWater.js
import React from 'react';
export default class AddWater extends React.Component {
handleAddQuantity = (e) => {
e.preventDefault();
const quantity = e.target.elements.quantity.value;
console.log(quantity);
};
render() {
return (
<form onSubmit={this.handleAddQuantity}>
<input type="text" name="quantity" />
<input type="submit" value="Submit" />
</form>
)
}
}
WaterElements.js
import React from 'react';
const WaterElements = (props) => (
<div>
<p>Water Quantity:</p>
{
props.quantities.map((quantity) =>
<p key={quantity}>{quantity}</p>
)
}
</div>
);
export default WaterElements;
I expect list to be ddddd, eeeee at this moment.
You're never calling props.handleAddQuantity
export default class AddWater extends React.Component {
handleAddQuantity = (e) => {
e.preventDefault();
const quantity = e.target.elements.quantity.value;
props.handleAddQuantity(quantity)
};
render() {
return (
<form onSubmit={this.handleAddQuantity}>
<input type="text" name="quantity" />
<input type="submit" value="Submit" />
</form>
)
}
this.setState(() => ({
quantities: ['ddddd', 'eeeee']
}));
should be
this.setState({
quantities: ['ddddd', 'eeeee']
});
and after for add
this.setState({
quantities: [...state.quantities, quantity]
});
to update use this format
this.state({key:value});
not this.state(()=>{key:value});
handleAddQuantity = (quantity) => {
this.setState({
quantities: ['ddddd', 'eeeee']
}));
console.log('works');
}

React/redux input values not showing

I am using react/redux with redux-form and for some reason the input values are not showing on my edit form.
I console.log my post and it shows that they are there, but for some reason it is not working. I will post code below.
edit component:
import React , { Component } from 'react';
import * as actions from '../../actions/posts_actions';
import { reduxForm, Field } from 'redux-form';
import {connect} from 'react-redux';
import {Link} from 'react-router-dom';
class EditPost extends Component {
componentDidMount() {
const {id} = this.props.match.params;
this.props.getOnePost(id);
}
renderField(field) {
const { meta: {touched, error} } = field;
const className = `form-group ${touched && error ? 'has-danger' : ''}`;
return (
<div className={className}>
<label><strong>{field.label}:</strong></label>
<input
className="form-control"
type={field.type}
value={field.value}
{...field.input}
/>
<div className="text-help">
{ touched ? error : ''}
</div>
</div>
)
}
onSubmit(values) {
const {id} = this.props.match.params;
this.props.updatePost(values, id, () => {
this.props.history.push(`/posts/${id}`);
});
}
render() {
const {handleSubmit} = this.props;
const {post} = this.props;
if(!post) {
return <div> Loading... </div>;
}
console.log(post);
return (
<form onSubmit={handleSubmit(this.onSubmit.bind(this))}>
<Field
label="Title"
name="title"
type="text"
value={post.title}
component={this.renderField}
/>
<Field
label="Content"
name="content"
type="text"
value={post.content}
component={this.renderField}
/>
<button type="submit" className="btn btn-success">Submit</button>
<Link to={`/posts/${post._id}`} className="btn btn-danger">Cancel</Link>
</form>
);
}
}
function validate(values) {
const errors = {};
if(!values.title) {
errors.title = "Enter a title!";
}
if(!values.content) {
errors.content = "Enter some content please!";
}
return errors;
}
function mapStateToProps({ posts }, ownProps) {
return { post: posts[ownProps.match.params.id] };
}
export default reduxForm({
validate,
form: 'editform'
})(connect(mapStateToProps, actions)(EditPost));
Instead of setting the value directly, pass an initialValues prop:
function mapStateToProps({ posts }, ownProps) {
const post = posts[ownProps.match.params.id]
return {
post,
initialValues: {
...post
}
};
}
remove value props from Fields in your form. So long as the properties on your Post object are the same as the name of the field you want to populate, you can just use object spread. If they are different, you'll have to map them appropriately
initialValues: {
contentField: post.content
}
<Field name="contentField" />
initial values have to be set before you use the reduxForm enhancer. Also, because I know it'll come up (and trust me, it always comes up eventually), if you want your form values to update if your model updates, you'll have add enableReinitialize: true to reduxForm's config

how to map values in material ui auto-complete

I have got data from firebase in "arr" but I dont know how can I use material-ui Auto-Complete? how Can I map "arr" data in Auto-Complete field?
import React, { Component } from 'react'
import { Link, browserHistory } from 'react-router';
import { connect } from 'react-redux'
import RaisedButton from 'material-ui/RaisedButton';
import { DBfirebase } from '../../Database/DBfirebase'
import { signUp } from '../../Store/Actions/Auth'
import TextField from 'material-ui/TextField';
import AppBar from 'material-ui/AppBar';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import AutoComplete from 'material-ui/AutoComplete';
import * as firebase from 'firebase';
import { Search } from '../../Store/Actions/Auth'
class AddProduct extends Component {
constructor() {
super();
this.state = {
arr: [],
productName: '',
description: '',
company:''
}
this.submit = this.submit.bind(this);
this.inputHandler = this.inputHandler.bind(this);
this.onSearch = this.onSearch.bind(this);
this.handleUpdateInput = this.handleUpdateInput.bind(this);
}
inputHandler(e) {
this.setState({
[e.target.name]: e.target.value
})
}
submit(e) {
e.preventDefault();
let multipath = {};
let productDetails = {
productName: this.state.productName,
description: this.state.description,
company: this.state.company,
}
console.log(productDetails)
DBfirebase.refAddProduct.push(productDetails);
browserHistory.push('/home/view-purchases')
}
//working code
onSearch(e) {
let _self = this;
// e.preventDefault()
let ref = firebase.database().ref().child('/AddedProducts/');
_self.arr = [];
// console.log(this.refs.selectedCity.value)
// ref.orderByChild('city').equalTo(this.refs.selectedCity.value).once('value', function (snapshot) {
ref.once('value', function (snapshot) {
snapshot.forEach(childSnapshot => {
_self.arr.push(childSnapshot.val())
console.log("arr", _self.arr)
})
_self.props.serachProducts(_self.arr)
_self.setState({
arr: _self.props.storeReducer.products
})
});
}
componentWillMount(){
this.onSearch();
}
handleUpdateInput = (value) => {
this.setState({
arr: [
value,
value + value,
value + value + value,
],
});
};
render() {
return (
<div ><center>
<AddProductForm signUpState={this.state} _inputHandler={this.inputHandler} _submit={this.submit} />
</center>
</div>
);
}
}
// AddProduct.contextTypes = {
// router: React.PropTypes.object.isRequired
// }
const dataSourceConfig = {
text: 'textKey',
value: 'valueKey',
};
class AddProductForm extends React.Component {
render() {
console.log("this.props.signUpState.arr",this.props.signUpState.arr)
const datasource = this.props.signUpState.arr;
return (
<div >
<h1>Add New Product</h1>
<form onSubmit={this.props._submit} >
<AutoComplete
hintText="Product Name"
filter={AutoComplete.noFilter}
openOnFocus={true}
// dataSource={this.props.signUpState.arr}
dataSource={datasource}
onUpdateInput={this.props.signUpState.handleUpdateInput}
dataSourceConfig={dataSourceConfig}
/>
<TextField
hintText="Product Name"
name="productName"
value={this.props.signUpState.productName}
floatingLabelText="Product Name"
onChange={this.props._inputHandler}
/><br /><br />
<TextField
type="text"
hintText="description"
name="description"
value={this.props.signUpState.description}
floatingLabelText="description"
onChange={this.props._inputHandler}
/><br /><br />
<TextField
type="text"
hintText="company"
name="company"
value={this.props.signUpState.company}
floatingLabelText="company"
onChange={this.props._inputHandler}
/><br />
<br />
<RaisedButton type="submit" label="Add Product" primary={false} secondary={true} /> <br /><br />
</form>
</div>
)
}
}
AddProductForm.PropTypes = {
_inputHandler: React.PropTypes.func.isRequired,
_submit: React.PropTypes.func.isRequired
}
const mapStateToProps = (state) => {
console.log(state.ProductReducer)
return {
storeReducer: state.ProductReducer
}
}
const mapDispatchToProps = (dispatch) => {
return {
serachProducts: (data) => {
console.log(data)
dispatch(Search(data))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AddProduct);
I have got data from firebase in "arr" but I dont know how can I use material-ui Auto-Complete? how Can I map "arr" data in Auto-Complete field?
Actually data from firebase come in object... So first get the keys of object using Object.keys(objectname) then store all keys in Array ... After getting the keys of object then start mapping on Arrays of key and in map call ur object with keys like obj[keys] ..
import React, { Component } from 'react'
import { Link, browserHistory } from 'react-router';
import { connect } from 'react-redux'
import RaisedButton from 'material-ui/RaisedButton';
import { DBfirebase } from '../../Database/DBfirebase'
import { signUp } from '../../Store/Actions/Auth'
import TextField from 'material-ui/TextField';
import AppBar from 'material-ui/AppBar';
import SelectField from 'material-ui/SelectField';
import MenuItem from 'material-ui/MenuItem';
import AutoComplete from 'material-ui/AutoComplete';
import * as firebase from 'firebase';
import { Search } from '../../Store/Actions/Auth'
class AddProduct extends Component {
constructor() {
super();
this.state = {
arr: [],
productName: '',
description: '',
company:''
}
this.submit = this.submit.bind(this);
this.inputHandler = this.inputHandler.bind(this);
this.onSearch = this.onSearch.bind(this);
this.handleUpdateInput = this.handleUpdateInput.bind(this);
}
inputHandler(e) {
this.setState({
[e.target.name]: e.target.value
})
}
submit(e) {
e.preventDefault();
let multipath = {};
let productDetails = {
productName: this.state.productName,
description: this.state.description,
company: this.state.company,
}
console.log(productDetails)
DBfirebase.refAddProduct.push(productDetails);
browserHistory.push('/home/view-purchases')
}
//working code
onSearch(e) {
let _self = this;
// e.preventDefault()
let ref = firebase.database().ref().child('/AddedProducts/');
_self.arr = [];
// console.log(this.refs.selectedCity.value)
// ref.orderByChild('city').equalTo(this.refs.selectedCity.value).once('value', function (snapshot) {
ref.once('value', function (snapshot) {
snapshot.forEach(childSnapshot => {
_self.arr.push(childSnapshot.val())
console.log("arr", _self.arr)
})
_self.props.serachProducts(_self.arr)
_self.setState({
arr: _self.props.storeReducer.products
})
});
}
componentWillMount(){
this.onSearch();
}
render() {
return (
<div ><center>
<AddProductForm signUpState={this.state} _inputHandler={this.inputHandler} _submit={this.submit} />
</center>
</div>
);
}
}
// AddProduct.contextTypes = {
// router: React.PropTypes.object.isRequired
// }
class AddProductForm extends React.Component {
render() {
console.log("this.props.signUpState.arr",this.props.signUpState.arr)
{ this.props.signUpState.arr.map((v, i) => {
return (
datasource.push(v.productName)
)
})}
return (
<div >
<h1>Add New Product</h1>
<form onSubmit={this.props._submit} >
<AutoComplete
hintText="Product Name"
filter={AutoComplete.noFilter}
openOnFocus={true}
// dataSource={this.props.signUpState.arr}
dataSource={datasource}
// onUpdateInput={this.props.signUpState.handleUpdateInput}
// dataSourceConfig={dataSourceConfig}
/>
<TextField
hintText="Product Name"
name="productName"
value={this.props.signUpState.productName}
floatingLabelText="Product Name"
onChange={this.props._inputHandler}
/><br /><br />
<TextField
type="text"
hintText="description"
name="description"
value={this.props.signUpState.description}
floatingLabelText="description"
onChange={this.props._inputHandler}
/><br /><br />
<TextField
type="text"
hintText="company"
name="company"
value={this.props.signUpState.company}
floatingLabelText="company"
onChange={this.props._inputHandler}
/><br />
<br />
<RaisedButton type="submit" label="Add Product" primary={false} secondary={true} /> <br /><br />
</form>
</div>
)
}
}
AddProductForm.PropTypes = {
_inputHandler: React.PropTypes.func.isRequired,
_submit: React.PropTypes.func.isRequired
}
const mapStateToProps = (state) => {
console.log(state.ProductReducer)
return {
storeReducer: state.ProductReducer
}
}
const mapDispatchToProps = (dispatch) => {
return {
serachProducts: (data) => {
console.log(data)
dispatch(Search(data))
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AddProduct);

after bind MapDispatchtoProps Can't use this.props

i try to figure out what's wrong in my code. can someone help me find out whats wrong. i use webstorm for text editing, and it's show "unresolve variable" in
this.props.loginUser(value);
is there any related to this?
this is my code :
import React, { Component } from 'react'
import {reduxForm, Field} from 'redux-form';
import { loginUser } from '../actions/index';
import { Stores } from '../Stores';
import {connect} from 'react-redux';
const validate = values => {
const errors = {};
if (!values.email) {
errors.email = 'Required'
} else if (!/^[A-Z0-9._%+-]+#[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
errors.email = 'Invalid email address'
}
if (!values.password) {
errors.password = 'Required'
}
return errors
};
const renderField = ({ input, label, type, meta: { touched, error } }) => (
<div>
<label>{label}</label>
<div>
<input {...input} placeholder={label} type={type} className="form-control"/>
{touched && error && <span className="alert alert-danger">{error}</span>}
</div>
</div>
);
function submit(value){
console.log(value);
this.props.loginUser(value); //didn't work
// Stores.dispatch(loginUser({email,password})); //this method work
}
class LoginV6 extends Component{
render() {
const {handleSubmit, pristine, reset, submitting} = this.props;
return (
<div className="row">
<div className="col-md-6">
<form onSubmit={handleSubmit(submit)}>
<div className="form-group">
<Field
name="email"
type="text"
component={renderField}
label="Email"
/>
</div>
<div className="form-group">
<Field
name="password"
type="password"
component={renderField}
label="Password"
/>
</div>
<div>
<button type="submit" className="btn btn-primary" disabled={pristine||submitting}>
Login
</button>
<button type="button" className="btn btn-primary" disabled={pristine || submitting}
onClick={reset}>
Clear Values
</button>
</div>
</form>
</div>
</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
return {
loginUser() {
dispatch({loginUser(value));
}
}
};
function mapStateToProps(state) {
return {
errorMessage: state.auth.error,
authenticated:state.auth.authenticated
}
}
LoginV6 = reduxForm({
form:'LoginV6',
validate
})(LoginV6);
export default LoginV6 = connect(mapStateToProps, mapDispatchToProps)(LoginV6);
this is my action code :
import axios from 'axios';
import jwtdecode from 'jwt-decode';
import {browserHistory} from 'react-router';
import {
AUTH_USER,
AUTH_ERROR,
USER_INFO_SUCCESS,
USER_INFO,
LOGOUT_USER,
GET_TABPANEL,
GET_SETUP_TABTITLES,
} from './types';
const ROOT_URL = 'http://localhost:8000';
// User and Auth actions
//
export function loginUser({email,password}){
return function(dispatch){
axios.post(`${ROOT_URL}/api/auth/login`,{email,password})
.then(response => {
dispatch({type: AUTH_USER,
payload:response.data.token
});
localStorage.setItem('laravel_user_token',response.data.token);
console.log('Login Success');
browserHistory.push("/");
}).catch(()=>{
dispatch(authError("Empty Required Field"));
});
}
}
if i use Stores.dispatch(loginUser(value)); it works.
Change your code like this:
class LoginV6 extends Component{
constructor(){
this.submit = this.submit.bind(this); //Because ES6 is not auto bind
}
submit(value){
//...your code
this.props.loginUser(value); //it will work
// or "loginUser" is an action
this.props.dispatch(loginUser(value)); //see the new function mapDispatchToProps
}
render(){
//...your code
}
}
// ....
// instead map a new object, we map dispatch directly
// with this function, we avoid duplicated/confused about actions in case you have many actions
const mapDispatchToProps = (dispatch) => {
return {
dispatch
}
};
i already fix this by change my code to this :
class LoginV6 extends Component{
submit = (data) => {
console.log(data);
this.props.loginUser(data);
}
render() {
const {handleSubmit, pristine, reset, submitting} = this.props;
return (
<div className="row">
<div className="col-md-6">
<form onSubmit={handleSubmit(this.submit)}>
..............................the rest of code..............................................
const mapDispatchToProps = (dispatch) => {
return {
loginUser: (data) => {
dispatch(loginUser(data))
}
}
}
function mapStateToProps(state) {
return {
errorMessage: state.auth.error,
authenticated:state.auth.authenticated
}
}
LoginV6 = reduxForm({
form:'LoginV6',
validate
})(LoginV6);
export default LoginV6 = connect(mapStateToProps, mapDispatchToProps)(LoginV6);

Resources