post api request with json input fields in reactjs - javascript

i have form with three input fields with type as
i have design the form but how to send data as object in gcloud field ?
code for gcloud input field:
<label>gcloud keyfile json</label>
<TextareaAutosize
name="gcloud_keyfile"
type="text"
id="gcloud_keyfile"
value={values.gcloud_keyfile}
onChange={handleChange}
/>
while for form submission i have used formik and code is shown below :
const initialValues = {
organ: "",
env: "",
gcloud_keyfile: "" ,
};
const { values, errors, touched, handleBlur, handleChange, handleSubmit } =
useFormik({
initialValues,
validationSchema: GcpSchema,
onSubmit: async (values, action) => {
try {
let response = await axios.post(
`${state.baseUrl}accounts/gcp/`,
{
organization: values.organ,
environment: values.env,
gcloud_keyfile_json: JSON.stringify(values.gcloud_keyfile),
});
if (response.status === 200) {
setMsg("You Are Successfully Create the Account");
action.resetForm();
return Promise.resolve();
}
} catch (error) {
console.error("There was an error!", error);
}
},
});
i have used json stringify but that doesn't work

i used JSON.parse(gcloud_keyfile_json)
to convert string into object and apply validation on the input field to take only object value

Related

How can I set all the key of an object state to empty array and change just one of them in React js

I'm creating sign up form with next js and I'm handling errors with joi.js, After Fetching the data if there is error, I want if the error is in the name input I will pass it as value of the name key in the errors state and pass an empty string to the other keys (email and password), and same thing for other errors, I tried to do it but when there is no error , the keys in the errors state have always the past values.
(Sorry for my bad English)
File where I fetch data Login.tsx
export default function Login() {
const [data, setData] = useState({ name: "", email: "", password: "" });
const [errors, setErrors] = useState({
name: "",
email: "",
password: "",
});
const handleChange = (e) => {
setData({
...data,
[e.target.name]: e.target.value,
});
};
const handleSubmit = async (e) => {
e.preventDefault();
const res = await fetch("/api/users", {
body: JSON.stringify(data),
headers: {
"Content-Type": "application/json",
},
method: "POST",
}, { cache: 'no-store' });
const content = await res.json();
if(content.error) {
setErrors({...errors, [content.error[0].path[0]]:content.error[0].message})
}
console.log(errors);
};
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
There will always be the old values in the errors state variable since you're setting the new error by spreading the old ones first:
setErrors({...errors, *****})
What does your content.error contain? I can see you're only accessing the first element (content.error[0]), but do you receive all errors for that submission? If you do, you don't need to spread the old errors, just run through all of the reported errors from the response and recreate your errors object.

Joi form validation: removing displayed errors

Here is a link to codesandbox example (Svelte). It represents a trivial register from being validated with Joi. The issue I'm facing is with clearing Joi validation error messages. I'm recording them in errors object, keys named by the input name (email, password, passwordConfirm).
Validations happens via function attached to form on:input
const validate = async e => {
const fields = { [e.target.name]: e.target.value };
try {
errors[Object.keys(fields)[0]] = null;
await registerSchema.validateAsync(
{ ...fields },
{ abortEarly: false, allowUnknown: true }
);
} catch (err) {
errors[Object.keys(fields)[0]] = err;
}
};
Its crude but it mostly works. It clears email and password errors alright but whatever I do passwordConfirm persists.
I don't think the issue is with my Joi schema:
export const registerSchema = Joi.object({
email: Joi.string().email({ tlds: { allow: false } }),
password: Joi.string().pattern(new RegExp("^[a-zA-Z0-9]{6,30}$")).trim(),
passwordConfirm: Joi.string().valid(Joi.ref("password")).trim()
});
Am pretty sure that the bug hides somewhere in the validate function itself but - for the death of me - I can find it. I would appreciate couple of hints here.
Again, example can be seen on codesandbox.
Your problem is indeed in your validate function. When you build your fields object, the only key you add to it is the currently active input:
const fields = { [e.target.name]: e.target.value };, meaning that when you compare passwordConfirm to Joi.ref('password') in your schema, the latter is always an empty value because there is no password key in the object being validated!
One (crude) way around that is to make sure the password field is passed into the object being validated when the active input is passwordConfirm:
const validate = async e => {
const fields = { [e.target.name]: e.target.value };
if (e.target.name === 'passwordConfirm') {
fields.password = password;
}
// console.log(fields); // log object being validated
try {
errors[Object.keys(fields)[0]] = null;
await registerSchema.validateAsync(
{ ...fields },
{ abortEarly: false, allowUnknown: true }
);
} catch (err) {
errors[Object.keys(fields)[0]] = err;
}
};
Tested in your CodeSandbox and seemed to work as intended.

how to get user input values and post them with axios

I've built a contact form and I'm trying to get my user inputted values to post using axios so I then get an email with the data inputted by the user.
I keep getting undefined values in my emails being sent. My server side is fine, I'm not to worried about that. What's the best approach for this?
document.querySelector(".contact-btn").addEventListener("click", sendIt);
function sendIt(event) {
event.preventDefault();
axios
.post("https://us-central1-selexin-website.cloudfunctions.net/app/sendemail", {
name: "",
email: "",
number: "",
message: "",
})
.then((res) => {
console.log(res);
});
}
this might work, also you can re-read documentation on POST Request Axios Documentation
For Live view how it works you can check on CODEPEN
const form = document.querySelector("form")
const input = document.querySelector("input")
const submitUser = () => {
axios.post('https://us-central1-selexin-website.cloudfunctions.net/app/sendemail', {
firstName: input.value,
})
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
form.addEventListener("submit", (e) => {
submitUser()
e.preventDefault()
})
<form>
<input type="text">
<button type="submit">Submit</button>
</form>

Making post request with React

In my React application, I have a form with only username and password (later I will add "confirm password" as well), when submitting a request with JSON should be send that contains the email and password in its body.
Password can only be accepted after few checks and if it passes all of those conditions then it will be accepted.
render() {
return (
<form className="demoForm" onSubmit={this.handleUserInput} >
.
.
.
.
<button type="submit" className="btn btn-primary" disabled={!this.state.formValid}>Sign U p</button>
</form>
);
}
handleUserInput = (e) => {
const name = e.target.name;
const value = e.target.value;
this.setState({[name]: value}, () => { this.validateField(name, value) });
axios.post('****', {
value
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
}
I am using axios like above, my problem is that I dont know what should be instead of this ****, I am using local host. Is this a good way to do this?
You should add the address you are posting your call to. (i.e. /api/validate_user)
Just on a side note, try separating your actions.
onChangeHandler(e) {
e.preventDefault()
const { value, id} = e.target
this.setState({
[id]: value
})
}
to update the state and then to submit
onSubmitHandler(e) {
var self = this;
e.preventDefault()
const { userName, password } = this.state;
// Do validation of password
axios.post('/api/validateUser', {
user: userName,
password: password
}).then(e => {
if(e.success){
console.log("success")
}
else if(e.error) {
console.log("error logging in")
}
})
}

React Formik not handling errors properly

I'm using the basic Formik template to work on a Login Form.
onSubmit={(
values,
{ setSubmitting, setErrors /* setValues and other goodies */ }
) => {
props.logMeIn(values);
// LoginToSystem(values).then(
// user => {
// setSubmitting(false);
// // do whatevs...
// // props.updateUser(user)
// },
// errors => {
// setSubmitting(false);
// // Maybe transform your API's errors into the same shape as Formik's
// //setErrors(transformMyApiErrors(errors));
// console.log(errors);
// }
// );
}}
This problem is within the onSubmit section; The demo code is commented out but it uses a LoginToSystem function that seems to be a promise. I can not figure out 'what' this function is supposed to me. My function that handles this would be props.logMeIn() - Which also does not work as intended
If the login is successful, it will currently work as expected, and everything is fine. However, if the login fails (404, 401, whatever) the form will remain there, and the setSubmitting log stays there so Submit is grayed out but nothing is done.
If I try to replace LoginToSystem with my function, I get an error on the .then that I can't perform .then on undefined.
I'm wondering if perhaps this is because my function is not set up like a Promise?
loginClickHandler = (user) => {
let userObj = {
email: user.email,
password: user.password
}
axios.post('api/v1/auth/sign_in', userObj)
.then((res) => {
console.log(res.headers);
let loggedInUser = {
'access_token': res.headers['access-token'],
'client': res.headers['client'],
'uid':res.headers['uid'],
'signedIn': true
};
this.setState({
user: loggedInUser
})
this.props.retrieve(user.email);
})
.catch((err) => {
console.log(err);
return err
})
};
My function does properly catch (Thanks to axios) on the .then/.catch, but perhaps I am supposed to modify those to provide a callback so that onSubmit can properly fire?
With some guidance I was able to resolve this one simpler. Axios is natively returning a 'promise' so I just needed to ensure the outcome of the function was axios' method in the end.
loginClickHandler = (user) => {
let userObj = {
email: user.email,
password: user.password
}
const request = axios.post('api/v1/auth/sign_in', userObj);
request.then((res) => {
console.log(res.headers);
let loggedInUser = {
'access_token': res.headers['access-token'],
'client': res.headers['client'],
'uid': res.headers['uid'],
'signedIn': true
};
this.setState({user: loggedInUser, auth: true, anchorEl: null})
}).catch((err) => {
console.log(err);
// setErrors({ test: 'This was an error' })
})
return request;
};
In onSubmit there's a second argument for setting your errors. I added flow to be able to see the types better in this answer for you.
<Formik
initialValues={...}
... // Other Props
onSubmit={this.handleSubmit} // This is where you handle your login logic
render={this.renderForm} // Render your form here.
You have a callback to help you set errors in the second argument
handleSubmit = (
user: FormValues,
{ setErrors }: FormikActions<FormValues>
) => {
return axios.post('api/v1/auth/sign_in', userObj)
...
.catch(e) => {
setErrors({ username: 'Invalid Username' }) // Object you want to put here.
}
}
In your render form function you now have errors that you can use based on what you called in your setErrors
renderForm = ({
... // These are your other FormikProps you're using
errors // You want to use this
}: FormikProps<FormValues>) => (
... // Your rendering here
// errors.username
)
For flow types on Formik
https://github.com/flowtype/flow-typed/blob/master/definitions/npm/formik_v0.9.x/flow_v0.53.x-/formik_v0.9.x.js

Categories