Axios Post Form with Reactjs - javascript

So I have this post method with Axios and if I submit this, it said
Uncaught (in promise) Error: Network Error
at createError (createError.js:16)
at XMLHttpRequest.handleError (xhr.js:87)
If I use this method:
axios.post('http://localhost:5000/users', ({userid: this.state.userid})
it works. But if I add 2 or more arg to the axios post it gets error again:
axios.post('http://localhost:5000/users', ({userid: this.state.userid}, {fullname: this.state.fullname} ))
Here is my full code. As you can see I try different combinations of code, and it only works if I only pass 1 arg.
import React from 'react';
import axios from 'axios';
// import { Form } from 'antd';
// import { List, Card, Form } from 'antd';
export default class FormUser extends React.Component {
// constructor(props) {
// super(props)
// this.state = {
state = {
userid: '',
fullname: '',
usergroup:'',
emailid: '',
mobile: '',
title: '',
};
handleChange = event => {
this.setState({ userid: event.target.value });
this.setState({ fullname: event.target.value });
this.setState({ usergroup: event.target.value });
this.setState({ emailid: event.target.value });
this.setState({ mobile: event.target.value });
this.setState({ title: event.target.value });
}
handleSubmit = event => {
event.preventDefault();
// const userform = {userid: this.state.userid};
// const fullnameForm = {fullname: this.state.fullname};
// const usergroupForm = {usergroup: this.state.usergroup};
// const emailidForm = {emailid: this.state.emailid};
// const mobileForm = {mobile: this.state.mobile};
// const titleForm = {title: this.state.title};
axios.post('http://localhost:5000/users', ({userid: this.state.userid}, {fullname: this.state.fullname} ))
// { {userid: this.state.userid}, {fullname: this.state.fullname} , usergroup: this.state.usergroup, emailid: this.state.emailid, mobile: this.state.mobile, title: this.state.title })
// { userform, fullnameForm, usergroupForm, emailidForm, mobileForm, titleForm })
.then(res => {
console.log(res);
console.log(res.data);
})
}
render() {
return (
<form onSubmit={this.handleSubmit}>
<label>User Project ID: <input type="text" name="userid" onChange={this.handleChange}/></label><br/>
<label>Full Name: <input type="text" name="fullname" onChange={this.handleChange}/></label><br/>
<label>User Group: <input type="text" name="usergroup" onChange={this.handleChange}/></label><br/>
<label>Email: <input type="text" name="emailid" onChange={this.handleChange}/></label><br/>
<label>Mobile: <input type="text" name="mobile" onChange={this.handleChange}/></label><br/>
<label>Title: <input type="text" name="title" onChange={this.handleChange}/></label>
<button type="submit">Add</button>
</form>
)
}
}
AXIOS POST on Express
app.post('/users', function (req, res) {
var postData = req.body;
// postData.created_at = new Date();
connection.query("INSERT INTO users SET ?", postData, function (error, results, fields) {
if (error) throw error;
console.log(results.insertId);
res.end(JSON.stringify(results));
});
});

eventHandler for each state. Is there any way I can do this better?
yes it would work something like this
import React, { Component } from 'react';
class UserForm extends Component {
constructor() {
super();
this.state = {
fname: '',
lname: '',
email: '',
};
}
onChange = (e) => {
/*
Because we named the inputs to match their
corresponding values in state, it's
super easy to update the state
*/
this.setState({ [e.target.name]: e.target.value });
}
render() {
const { fname, lname, email } = this.state;
return (
<form>
<input
type="text"
name="fname"
value={fname}
onChange={this.onChange}
/>
<input
type="text"
name="lname"
value={lname}
onChange={this.onChange}
/>
<input
type="text"
name="email"
value={email}
onChange={this.onChange}
/>
</form>
);
}
}
and about submission of the form your axios post would work something like this
onSubmit = (e) => {
e.preventDefault();
// get our form data out of state
const { fname, lname, email } = this.state;
axios.post('/', { fname, lname, email })
.then((result) => {
//access the results here....
});
}

axios.post(url[, data[, config]])'s 3rd argument is the Axios configuration object, which you're inadvertently passing in in
axios.post('http://localhost:5000/users', ({userid: this.state.userid}, {fullname: this.state.fullname} ))
so the request gets misconfigured and doesn't work.
Instead, all of the data to POST should be in the single data object.
axios.post('http://localhost:5000/users', {
userid: this.state.userid,
fullname: this.state.fullname,
})

So apparently I have to add eventhandler for each state. Is there any way I can do this better?
import React from 'react';
import axios from 'axios';
import { Form } from 'antd';
// import { List, Card, Form } from 'antd';
const FormItem = Form.Item;
export default class FormUser extends React.Component {
// constructor(props) {
// super(props)
// this.state = {
state = {
userid: '',
fullname: '',
usergroup: '',
emailid: '',
mobile: '',
title: '',
};
handleUserIDChange = event => {this.setState({ userid: event.target.value })}
handleFullNameChange = event => {this.setState({ fullname: event.target.value })}
handleUserGroupChange = event => {this.setState({ usergroup: event.target.value })}
handleEmailIDChange = event => {this.setState({ emailid: event.target.value })}
handleMobileChange = event => {this.setState({ mobile: event.target.value })}
handleTitleChange = event => {this.setState({ title: event.target.value })}
handleSubmit = event => {
event.preventDefault();
// const userform = {userid: this.state.userid};
// const fullnameForm = {fullname: this.state.fullname};
// const usergroupForm = {usergroup: this.state.usergroup};
// const emailidForm = {emailid: this.state.emailid};
// const mobileForm = {mobile: this.state.mobile};
// const titleForm = {title: this.state.title};
axios.post('http://localhost:5000/users',
{ userid: this.state.userid, fullname: this.state.fullname, usergroup: this.state.usergroup, emailid: this.state.emailid, mobile: this.state.mobile, title: this.state.title },)
.then(res => {
console.log(res);
console.log(res.data);
})
}
render() {
return (
// const formItemLayout = {
// labelCol: {
// xs: { span: 24 },
// sm: { span: 8 },
// },
// wrapperCol: {
// xs: { span: 24 },
// sm: { span: 16},
// },
// };
<Form onSubmit={this.handleSubmit}>
<FormItem>
<label>User Project ID: <input type="text" name="this.state.userid" onChange={this.handleUserIDChange} /></label>
</FormItem>
<FormItem>
<label>Full Name: <input type="text" name="this.state.fullname" onChange={this.handleFullNameChange} /></label><br />
</FormItem>
<FormItem>
<label>User Group: <input type="text" name="this.state.usergroup" onChange={this.handleUserGroupChange} /></label><br />
</FormItem>
<FormItem>
<label>Email: <input type="text" name="this.state.emailid" onChange={this.handleEmailIDChange} /></label>
</FormItem>
<FormItem>
<label>Mobile: <input type="text" name="this.state.mobile" onChange={this.handleMobileChange} /></label>
</FormItem>
<FormItem>
<label>Title: <input type="text" name="this.state.title" onChange={this.handleTitleChange} /></label>
</FormItem>
<button type="submit">Add</button>
</Form>
)
}
}

Related

React - using nested objects as state with hooks to fill form data

I have a nested object as state like below -
const [userInfo, setUserInfo] = useState({
author:"",
user: {
name: 'rahul',
email: 'rahul#gmail.com',
phone: [{ primary: '8888888810' }, { alternate: '7777777716' }]
}
});
I want to have 5 input fields - author, name, email, primary, and alternate and want to use only one handleChange() method to change the fields.
You can find the code I wrote on the link - https://stackblitz.com/edit/react-ngpx7q
Here, I am not able to figure out how to update the state correctly. Any help would be greatly appreciated.
Since this was an interview question then I'd avoid 3rd-party libraries. You can use a switch statement to handle the differently nested state, namely the name and email in the second level and primary and alternate in the third level.
const handleChange = (e) => {
const { name, value } = e.target;
switch (name) {
case "name":
case "email":
setUserInfo((userInfo) => ({
user: {
...userInfo.user,
[name]: value
}
}));
break;
case "primary":
case "alternate":
setUserInfo((userInfo) => ({
user: {
...userInfo.user,
phone: userInfo.user.phone.map((el) =>
el.hasOwnProperty(name)
? {
[name]: value
}
: el
)
}
}));
break;
default:
// ignore
}
};
Demo
you can use lodash set to assign the value for the deeply nested object. You need to pass the path to the name prop of your input .
import set from 'lodash/set'
const App = () => {
const [userInfo, setUserInfo] = useState({
author:"",
user: {
name: 'rahul',
email: 'rahul#gmail.com',
phone: [{ primary: '8888888810' }, { alternate: '7777777716' }]
}
});
const handleChange = (e) => {
// clone the state
const userInfoCopy = JSON.parse(JSON.stringify(userInfo));
set(userInfoCopy, e.target.name, e.target.value)
setUserInfo(userInfoCopy)
}
console.log(userInfo)
return (
<div>
<input
name="user.name"
onChange={handleChange}
/>
<input
name="user.phone.[0].primary"
onChange={handleChange}
/>
</div>
);
};
Now you can use a single handleChange method for updating all your keys in the state .
Instead of treating phone as object of array, which i don't think is a good idea, treat it as single object with primary and alternate as key value pairs
import React, { useState } from 'react';
import './style.css';
export default function App() {
const [userInfo, setUserInfo] = useState({
user: {
name: 'ravi',
email: 'ravi#gmail.com',
phone: {
primary: 345345345345,
alternate: 234234234234
}
}
});
const handleChange = e => {
console.log(e.target.name);
setUserInfo(prevState => {
return {
user: {
...prevState.user,
[e.target.name]: e.target.value,
phone: {
...prevState.user.phone,
...{ [e.target.name]: e.target.value }
}
}
};
});
};
const {
name,
email,
phone: { primary, alternate }
} = userInfo.user;
console.log(userInfo);
return (
<div className="App">
Name: <input name="name" value={name} onChange={e => handleChange(e)} />
<br />
Email:{' '}
<input name="email" value={email} onChange={e => handleChange(e)} />
<br />
Primary:{' '}
<input name="primary" value={primary} onChange={e => handleChange(e)} />
<br />
Alternate:{' '}
<input
name="alternate"
value={alternate}
onChange={e => handleChange(e)}
/>
<br />
</div>
);
}
This works based on your original data (where phone is an array of objects):
const handleChange = e => {
let name = e.target.name;
if (['name', 'email'].includes(name)) {
setUserInfo(prevState => {
return {
user: {
...prevState.user,
[name]: e.target.value,
}
};
});
} else {
setUserInfo(prevState => {
return {
user: {
...prevState.user,
phone: name === 'primary' ?
[prevState.user.phone.find(e => Object.keys(e).includes('alternate')), {[name]: e.target.value}] :
[prevState.user.phone.find(e => Object.keys(e).includes('primary')), {[name]: e.target.value}]
}
};
});
}
};
I copy paste your code and only edit your handleChange
import React, { useState } from 'react';
import './style.css';
export default function App() {
const [userInfo, setUserInfo] = useState({
user: {
name: 'ravi',
email: 'ravi#gmail.com',
phone: [{ primary: '9999999990' }, { alternate: '9999998880' }]
}
});
const handleChange = e => {
console.log(e.target.name);
let arrPhone = userInfo.user.phone;
(e.target.name == 'primary' || e.target.name == 'alternate' )
&& arrPhone.map(x => (x.hasOwnProperty(e.target.name)) && (x[e.target.name] = e.target.value))
console.log(arrPhone)
setUserInfo(prevState => {
return {
user: {
...prevState.user,
[e.target.name]: e.target.value,
phone: arrPhone
}
};
});
};
const {
name,
email,
phone: [{ primary }, { alternate }]
} = userInfo.user;
console.log(userInfo);
return (
<div className="App">
Name: <input name="name" value={name} onChange={handleChange} />
<br />
Email: <input name="email" value={email} onChange={handleChange} />
<br />
Primary: <input name="primary" value={primary} onChange={handleChange} />
<br />
Alternate:{' '}
<input name="alternate" value={alternate} onChange={handleChange} />
<br />
</div>
);
}

Not able to get response while sending my data to backend in reactjs

I am using axios for sending my data using POST method.
This axios is not giving me response on the console.
Since, I have also used promise but still not able to get the response on console.
Notice: I am getting the data which I sent...flow of control is not entering into then() promise.
import "./SignUp.css";
import React, { Component } from "react";
import "../SignIn/SignIn.css";
import Organization from "../../Organization/organization";
import axios from "axios";
import { withRouter } from "react-router";
export class SignUp extends Component {
constructor() {
super();
this.state = {
firstName: "",
lastName: "",
password: "",
email: "",
organizationName: "",
};
this.handleFirstNameChange = this.handleFirstNameChange.bind(this);
this.handleLastNameChange = this.handleLastNameChange.bind(this);
this.handlePasswordChange = this.handlePasswordChange.bind(this);
this.handleOrganizationNameChange = this.handleOrganizationNameChange.bind(
this
);
this.handleSubmitLogin = this.handleSubmitLogin.bind(this);
this.handleEmailChange = this.handleEmailChange.bind(this);
}
handleFirstNameChange(event) {
this.setState({ firstName: event.target.value });
}
handleLastNameChange(event) {
this.setState({ lastName: event.target.value });
}
handleOrganizationNameChange(event) {
this.setState({ organizationName: event.target.value });
}
handlePasswordChange(event) {
this.setState({ password: event.target.value });
}
handleEmailChange(event) {
this.setState({ email: event.target.value });
}
async handleSubmitLogin() {
var organizationRecord = new Organization(
this.state.firstName,
this.state.lastName,
this.state.password,
this.state.email,
this.state.organizationName
);
const data = {
First_Name: organizationRecord.getFirstName,
Last_Name: organizationRecord.getLastName,
Password: organizationRecord.getPassword,
Email: organizationRecord.getEmail,
Organization_Name: organizationRecord.getOrganizationName,
};
// Code Starts here
try {
axios
.post("http://localhost:8000/Organization", data)
.then((result) => {
console.log(`Status Code: ${result.status}`);
})
.catch((err) => {
console.error(err);
});
sessionStorage.clear();
sessionStorage.setItem(
"email",
JSON.stringify(organizationRecord.getEmail)
);
this.props.history.push("/sign-in/redirect");
} catch (error) {
console.error(error);
}
//Code ends here
}
render() {
return (
<div className="sign-up-container">
<div className="sign-in-input">
<h2>SIGN UP</h2>
<div className="sign-in-input-inner">
<input
className="input"
value={this.state.firstName}
onChange={this.handleFirstNameChange}
type="text"
placeholder="First Name"
/>
<input
className="input"
type="text"
value={this.state.lastName}
onChange={this.handleLastNameChange}
placeholder="Last Name"
/>
<input
className="input"
type="email"
value={this.state.email}
onChange={this.handleEmailChange}
placeholder="Email"
/>
<input
className="input"
type="text"
value={this.state.organizationName}
onChange={this.handleOrganizationNameChange}
placeholder="Organization Name"
/>
<input
className="input"
type="password"
value={this.state.password}
onChange={this.handlePasswordChange}
placeholder="Password"
/>
<div
onClick={this.handleSubmitLogin}
className="sign-in-button-container sign-up-button-container"
>
Submit
</div>
</div>
</div>
</div>
);
}
}
export default withRouter(SignUp);
Can anyone explain me where I am lagging?

how can i clean the input value after i click the button?

the below code works fine, but it has a small issue, it did not clean an input field value when I click the button, so I have tried to put a code this.setState({ name: ''}) into nameChangedHandler that make this input value back to empty, but it does not work and will lock the input value to empty, and then you could not type any data into this input value.
Does it work by using Component Lifecycle?
class AddPerson extends Component {
state = {
name: '',
age: '',
};
nameChangedHandler = event => {
this.setState({ name: event.target.value });
};
ageChangedHandler = event => {
this.setState({ age: event.target.value });
};
render() {
return (
<div className="AddPerson">
<input
type="text"
placeholder="Name"
onChange={this.nameChangedHandler}
value={this.state.name}
/>
<input
type="number"
placeholder="Age"
onChange={this.ageChangedHandler}
value={this.state.age}
/>
<button onClick={() => this.props.personAdded(this.state.name, this.state.age)}>
Add Person
</button>
</div>
);
}
}
export default AddPerson;
You clean the name in the button's onClick handler:
<button onClick={() => {
this.props.personAdded(this.state.name, this.state.age);
this.setState({ name: '' });
}}>
Add Person
</button>
class AddPerson extends React.Component {
constructor(props) {
super(props);
this.state = {
name: "",
age: ""
};
}
nameChangedHandler = (event) => {
this.setState({ name: event.target.value });
};
ageChangedHandler = (event) => {
this.setState({ age: event.target.value });
};
handleSubmit = () => {
this.props.personAdded(this.state.name, this.state.age);
this.setState({
name: "",
age: ""
});
};
render() {
return (
<div className="AddPerson">
<input
type="text"
placeholder="Name"
onChange={this.nameChangedHandler}
value={this.state.name}
/>
<input
type="number"
placeholder="Age"
onChange={this.ageChangedHandler}
value={this.state.age}
/>
<button onClick={this.handleSubmit}>Add Person</button>
</div>
);
}
}
export default AddPerson;

React Context API does not update after calling dispatch

I have a login component that stores the user information in the global state after a successful login. The login component is pretty straight forward. It contains a form with a handleSubmit event that calls an endpoint. Based on the result of that endpoint an action is taken. The login component looks like this.
import React, { Component } from 'react';
import { StateContext } from '../state';
import { login } from '../repositories/authenticationRepository';
class Login extends Component {
static contextType = StateContext;
constructor(props) {
super(props);
this.state = {
email: '',
password: '',
message: '',
};
}
handleChange = (event) => {
const { name, value } = event.target;
this.setState({ [name]: value });
}
handleSubmit = async (event) => {
event.preventDefault();
const [{}, dispatch] = this.context;
const { history } = this.props;
const { email, password } = this.state;
const isLoggedInResponse = await login({ email, password });
if (isLoggedInResponse.data.type === 'error') {
this.setState({ message: isLoggedInResponse.data.message });
return;
}
dispatch({ type: 'storeUserInformation', userInformation: isLoggedInResponse.data.message });
history.push('/');
}
render() {
const { email, password, message } = this.state;
return (
<div className="login-wrapper">
<form onSubmit={this.handleSubmit}>
<label htmlFor="email">
Email:
<input autoComplete="off" name="email" type="text" value={email} onChange={this.handleChange} />
</label>
<label htmlFor="password">
Password:
<input autoComplete="off" id="password" name="password" type="password" value={password} onChange={this.handleChange} />
</label>
{message.length > 0 && <span className="text-danger error">{message}</span> }
<input className="btn btn-secondary" type="submit" value="Submit" />
</form>
</div>
);
}
}
export default Login;
When testing it myself I can see the user information being set in the ReactJS devtools. Of course I want to test this automatically using a unit test, so I wrote the following.
jest.mock('../../repositories/authenticationRepository');
import React from 'react';
import { mount } from 'enzyme';
import Login from '../../pages/Login';
import { StateProvider } from '../../state';
import { login } from '../../repositories/authenticationRepository';
import { act } from 'react-dom/test-utils';
import history from '../../sitehistory';
import { BrowserRouter as Router } from 'react-router-dom';
import { reducer } from '../../reducer';
it('Saves the user information in the store on a succesfull login', async () => {
login.mockReturnValue(({ data: { type: 'success', message: 'Message should be stored' }}));
let initialStateMock = {}
const wrapper = mount(
<StateProvider initialState={initialStateMock} reducer={reducer}>
<Router>
<Login history={history} />
</Router>
</StateProvider>
);
let emailEvent = { target: { name: 'email', value: 'test#example.com'} }
let passwordEvent = { target: { name: 'password', value: 'password'} }
wrapper.find('input').first().simulate('change', emailEvent);
wrapper.find('input').at(1).simulate('change', passwordEvent);
const submitEvent = { preventDefault: jest.fn() }
await act(async () => {
wrapper.find('form').first().simulate('submit', submitEvent);
});
act(() => {
wrapper.update();
});
console.log(initialStateMock); // expected { userInformation: 'Message should be stored' } but got {}
});
I expect the initialStatemock to have the value of { userInformation: 'Message should be stored' }. However it still has the initial value of {}. I tried wrapper.update() to force a refresh but to no avail. What am I overlooking?

value is not shown in the field when using redux form

I am using redux-form for the form. The form gets submitted but if page is refreshed
I need to show that submitted data which comes from the server. Everything is working,
the local state is also updated from getDerivedStateFromProps but the field does not
show with the data. I used plain input tag and it shows up the data. What have i missed?
Here is what I have done
UPDATE
const mapStateToProps = (state) => {
const { company } = state.profile.companyReducer;
return {
getCompany: state.profile.companyReducer,
initialValues: company && company.records,
};
};
const mapDispatchToProps = dispatch => ({
loadCompany: () => dispatch(loadCompany()),
saveCompany: companyData => dispatch(saveCompany(companyData)),
});
const withConnect = connect(
mapStateToProps,
mapDispatchToProps,
);
const withReduxForm = reduxForm({
form: 'companyForm',
fields: requiredFields,
validate,
// initialValues: {
// company_name: 'company',
// },
destroyOnUnmount: false,
enableReinitialize: true,
keepDirtyOnReinitialize: true,
});
const initialState = {
company_name: 'hello',
website: '',
industry: '',
number_of_employees: '',
phone_number: '',
founded: '',
address: '',
city: '',
state: '',
zip_code: '',
country: '',
wiki: '',
headquarter: '',
speciality: '',
type: '',
};
const enhance = compose(
withReduxForm,
withConnect,
withState('company', 'updateCompany', initialState),
withHandlers({
handleChange: props => ({ target: { name, value } }) => {
props.updateCompany({ ...props.company, [name]: value });
},
handleSubmit: props => (event) => {
event.preventDefault();
props.saveCompany(props.company);
},
}),
setStatic('getDerivedStateFromProps', (nextProps) => {
const { company } = nextProps.getCompany;
if (company && company.records !== undefined) {
console.log('company records getDerivedStateFromProps', company.records);
return {
company: company.records,
};
}
return null;
}),
lifecycle({
componentDidMount() {
this.props.loadCompany();
},
}),
);
export default enhance;
const Company = ({
company,
handleChange,
handleSubmit,
}: {
company: Object,
handleChange: Function,
handleSubmit: Function
}) => {
console.log('company', company);
return (
<React.Fragment>
<FormHeadline headline="Company" weight="400" />
<Wrapper>
<GridContainer container spacing={24}>
<StyledForm autoComplete="off" onSubmit={handleSubmit}>
<FormWrapper>
<input
name="company_name"
id="company_name"
type="text"
label="Company Name"
className="input-field"
value={company.company_name}
onChange={handleChange}
/>
{/* <Field
id="company_name"
name="company_name"
type="text"
label="Company Name"
className="input-field"
value="Hello"
onChange={handleChange}
component={GTextField}
required
margin="normal"
/> */}
<Field
id="website"
name="website"
type="text"
label="Website"
placeholder="Website"
className="input-field"
value={company.website}
onChange={handleChange}
component={GTextField}
required
margin="normal"
/>
</FormWrapper>
</StyledForm>
</GridContainer>
</Wrapper>
</React.Fragment>
);
};
export default enhance(Company);
generic text field
const GTextField = ({
input,
label,
meta: { touched, error },
...rest
}: {
input: any,
label: Node,
meta: {
touched: boolean,
error: boolean
}
}) => {
console.log('rest', input);
return (
<TextField
label={label}
helperText={touched && error}
error={!!(touched && error)}
{...input}
{...rest}
/>
);
};
This works but not the Field one
<input
name="company_name"
id="company_name"
type="text"
label="Company Name"
className="input-field"
value={company.company_name}
onChange={handleChange}
/>
UPDATE
props.initialValues shows the following but still the field is not updated
here is the full code
https://gist.github.com/MilanRgm/e3e0592c72a70a4e35b72bb6107856bc
Hi first replace the input tag with the commented out field component itself then set these flags in reduxform
const withReduxForm = reduxForm({
form: 'companyForm',
fields: requiredFields,
validate,
destroyOnUnmount: false,
enableReinitialize: true,
keepDirtyOnReinitialize: true
});
as well as pass the initialValues props to the form container with the server response
{
company_name: 'response value from server'
}
Hi checkout this fiddle link for initialValues example. For your example with reducer
const mapStateToProps = state => ({
getCompany: state.profile.companyReducer,
initialValues: state.profile.[your reducer object] });

Categories

Resources