this not working in async function in React component - reactjs

In my React component this.login() isn't executing. I believe this is because an await function changes the context of this, but I'm not sure how to fix it.
await this.props
.SignupUser({
variables: {
email: this.state.email,
password: this.state.password,
name: this.state.name,
},
})
.then(() => {
this.login();
})
.catch(error => {
this.setState({ wait: false });
const errorMessage = error.graphQLErrors[0].functionError;
this.setState({ error: errorMessage });
});

Remove await keyword, It should work.
Alternatively, we need to implement in a different way
The function must add async keyword in the function declaration for below code
await this.props
.SignupUser({
variables: {
email: this.state.email,
password: this.state.password,
name: this.state.name,
},
})
.then(() => {
this.login();
})
.catch(error => {
this.setState({ wait: false });
const errorMessage = error.graphQLErrors[0].functionError;
this.setState({ error: errorMessage });
});
(or)
try {
const user = await this.props
.SignupUser({
variables: {
email: this.state.email,
password: this.state.password,
name: this.state.name,
},
});
this.login();
} catch (e) {
this.setState({ wait: false });
const errorMessage = error.graphQLErrors[0].functionError;
this.setState({ error: errorMessage });
}

Related

why does this error occur during fetch data from the backend

I have a problem in the signin component when I try to login using the method that have been created below.
Here is the example of the code :
export default function Signin(props) {
const classes = useStyles();
const [values, setValues] = useState({
email: '',
password: '',
error: '',
redirectToReferrer: false,
});
const handleSubmit = () => {
const user = {
email: values.email || undefined,
password: values.password || undefined,
};
signin(user).then((data) => {
if (data.error) {
setValues({ ...values, error: data.error });
} else {
auth.authenticate(data, () => {
setValues({ ...values, error: '', redirectToReferrer: true });
});
}
});
};
const handleChange = (name) => (event) => {
setValues({ ...values, [name]: event.target.value });
};
const { from } = props.location.state || {
from: {
pathname: '/',
},
};
const { redirectToReferrer } = values;
if (redirectToReferrer) {
return <Redirect to={from} />;
}
}
If I save this code the error comes up:
can not read property state of undefined.
The login form appears when I comment out this {from}. But another error comes when I hit submit button:
cannot read property error of undefined.
Here is my sign in method :
const signin = async (user) => {
try {
let response = await fetch('http://localhost:4000/auth/signin', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
credentials: 'include',
body: JSON.stringify(user),
});
return await response.json();
} catch (err) {
console.log(err);
}
};
and the auth method:
const auth = {
authenticate(jwt, cb) {
if (typeof window !== 'undefined')
sessionStorage.setItem('jwt', JSON.stringify(jwt));
cb();
},
};
export default auth;
After reviewing your code, I see these two places you might get error:
props.location.state and data.error.
To resolve can not read property state of undefined, Add one more safe check:
const { from } = props.location && props.location.state || {
from: {
pathname: '/',
},
};
And for this one: cannot read property error of undefined
signin(user).then((data) => {
if (data && data.error) {
setValues({ ...values, error: data.error });
} else {
auth.authenticate(data, () => {
setValues({ ...values, error: '', redirectToReferrer: true });
});
}
});

React frontend + WordPress API create/register user with frontend registration form

I have an issue with frontend form submission with React Axios. Using WordPress API to create a user through the frontend registration form. The form has 3 fields username, email and password. Also, I have JWT plugin installed for the token authorisation. The current error is 400 bad request. And the catch error message is "Missing parameter(s): password"
const Register = ({ props }) => {
const [register, setRegister] = useState({
username: '',
email: '',
password: '',
userCreated: false,
loading: false,
token: '',
message: ''
})
const handleOnSubmit = e => {
e.preventDefault()
setRegister({ loading: true })
console.log(register)
const userData = {
username: e.target[0].value,
email: e.target[2].value,
password: e.target[4].value
//role: 'Administrator'
}
const authToken = localStorage.getItem('token')
axios.post('http://localhost:8888/react/wp-json/wp/v2/users', userData, {
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${authToken}`
}
})
.then(res => {
setRegister({
loading: false,
userCreated: !!res.data.id,
message: res.data.id ? 'New user created' : '',
})
console.log(res)
})
.catch(err => {
setRegister({
loading: false,
message: err.response.data.message,
})
console.log(err)
})
}
const handleOnChange = e => {
setRegister({ ...register, [e.target.name]: e.target.value })
console.log(register)
}
const { password, username, email, loading, error } = useState()
return ( my form here )

formik form reset on action dispatch

is there any possible ways to reset the form right after I dispatch the action ?
something like:
const formik = useFormik({
onSubmit: (values, {resetForm}) => {
dispatch(action.register(values)) //some action creator with axios.post request
if (isRegistred) { resetForm() } //isRegistred - value from Selector which changes on dispatch to true
}
})
const register = (user) => (dispatch) => {
return axios
.post(`${API_URL}/user/create/`, {
first_name: user.firstName,
second_name: user.secondName,
date_birth: user.dateBirth,
phone_number: user.phoneNumber,
gender: user.gender,
email: user.email,
city: user.city,
username: user.username,
password1: user.password1,
password2: user.password2
})
.then((response) => {
dispatch({ type: '#USER/register-success', isRegistred: response.data?.success })
})
.catch((error) => {
dispatch({ type: '#USER/register-error', error: error?.response?.data?.errors })
})
}
export const action = { register }
I know, it's kinda silly, because it's changing value right after.
Maybe there any other approaches ?
if someone intrested, i just pass the resetForm from onSubmit formik to action creator.
const formik = useFormik({
initialValues,
validationSchema,
onSubmit: (values, { resetForm }) => {
dispatch(userActions.register(values, { resetForm }))
},
validateOnChange: false,
validateOnBlur: true
})
const register = (user, { resetForm }) => (dispatch) => {
return axios
.post(`${API_URL}/user/create/`, {
first_name: user.firstName,
second_name: user.secondName,
date_birth: user.dateBirth,
phone_number: user.phoneNumber,
gender: user.gender,
email: user.email,
city: user.city,
username: user.username,
password1: user.password1,
password2: user.password2
})
.then((response) => {
dispatch({ type: '#USER/register-request' })
if (response.data?.success) {
dispatch({ type: '#USER/register-success', isRegistred: response.data?.success })
resetForm()
}
})
.catch((error) => {
dispatch({ type: '#USER/register-error', error: error?.response?.data?.errors })
})
}

Difference between .then and async/await in React

I need to PUT some data to backend, GET a response and use it to setState(), rendering the page syncronously. When using .then the changes made in editPost persist in about half of the time while using async/await seems to work fine(based on experimentation). I'm not sure why this happens since I've been told the two were equivalent:
.then:
onEditSubmit(e){
e.preventDefault()
const newPost = {
id: this.state.id,
title: this.state.titl,
author: this.state.auth,
content: this.state.cont
}
editPost(newPost)
.then(axios.get('/blog')
.then(response => {
this.setState({
posts: response.data,
titl: '',
auth: '',
cont: ''
})
}))
}
async/await:
async onEditSubmit(e){
e.preventDefault()
const newPost = {
id: this.state.id,
title: this.state.titl,
author: this.state.auth,
content: this.state.cont
}
await editPost(newPost)
var response = await axios.get('/blog')
await this.setState({
posts: response.data,
titl: '',
auth: '',
cont: ''
})
}
editPost:
export const editPost = editPost => {
return axios.put(`/blog/write/${editPost.id}`, {
title : editPost.title,
author : editPost.author,
content : editPost.content
})
}
Note: I'm not sure if the fact that setState() being async has to do with this.
You should have a callback function in the first promise:
onEditSubmit(e){
e.preventDefault()
const newPost = {
id: this.state.id,
title: this.state.titl,
author: this.state.auth,
content: this.state.cont
}
editPost(newPost)
.then(() => {
axios.get('/blog')
.then(response => {
this.setState({
posts: response.data,
titl: '',
auth: '',
cont: ''
})
})
})
}

React-Native Error "undefined is not an object (evaluating '_this2.onLoginSuccess.bind')"

I am following a simple example in react-native to log user in. I added following code to handle that
onButtonPress() {
const { email, password } = this.state;
this.setState({ error: '', loading: true });
firebase.auth().signInWithEmailAndPassword(email, password)
.then(this.onLoginSuccess.bind(this))
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(this.onLoginSucess.bind(this))
.catch(this.onLoginFail.bind(this));
});
}
onLoginSuccess() {
this.setState({
email: '',
password: '',
loading: false,
error: ''
});
}
onLoginFail() {
this.setState({
error: 'Authentication Failed',
loading: false
});
}
but I get error "undefined is not an object (evaluating '_this2.onLoginSuccess.bind')"
I am very new to react-native, so please explain.
You cannot bind() multiple times like that. To bind() in place is often and only works with anonymous function.
Do this instead:
constructor(props) {
super(props);
this.onLoginSuccess = this.onLoginSuccess.bind(this);
this.onLoginFailed = this.onLoginFailed.bind(this);
}
onButtonPress() {
const { email, password } = this.state;
this.setState({ error: '', loading: true });
firebase.auth().signInWithEmailAndPassword(email, password)
.then(this.onLoginSuccess)
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(this.onLoginSucess)
.catch(this.onLoginFail);
});
}
onLoginSuccess() {
this.setState({
email: '',
password: '',
loading: false,
error: ''
});
}
onLoginFail() {
this.setState({
error: 'Authentication Failed',
loading: false
});
}
onButtonPress() {
const { email, password } = this.state;
this.setState({ error: '', loading: true });
firebase.auth().signInWithEmailAndPassword(email, password)
.then(this.onLoginSuccess.bind(this))
.catch(() => {
firebase.auth().createUserWithEmailAndPassword(email, password)
.then(this.onLoginSucess.bind(this))
.catch(this.onLoginFail.bind(this));
});
}
onLoginSuccess = () => {
this.setState({
email: '',
password: '',
loading: false,
error: ''
});
}
onLoginFail = () => {
this.setState({
error: 'Authentication Failed',
loading: false
});
}
The annual problem I had is that I misspelled method name. Instead onLoginSuccess, I called it onLoginSucess

Resources