Basically I am creating a email form with react as view and express for the server. It is working fine.
Instead of redirecting on success I am just wanting to re render the form component on the contact page.
Is there anyway I can access the post request success value from within a react component? maybe calling a fetch method within the contact component that fetchs at the '/contact' end point? will this trigger the app.post() method within my express.js file??
this is my post request on button submit within react:
handleFormSubmit = (name, email, text) => {
axios.post('/contact', {
name: name,
email: email,
text: text
}).then(res => {
this.setState({sent: true})
console.log(this.state);
}).catch(err => {
console.log(err);
})
}
this is my express js post:
server.post('/contact', async (req, res) => {
try {
sendMail(req.body).then(info => console.log(info))
// I am getting a response here just fine
console.log(res)
} catch (error) {
console.log('express line 25: ', error);
}
});
I am using Next.js and nodemailer with GMail
Thanks
Ok sorry guys, problem has nothing to do with any code, its next js setup, i built it and ran and seems to be returning fine!
I don't see your code, but if we use fetch inside a React component, try using componentDidMount:
class Contact extends React.Component {
constructor(props) {
super(props);
this.state = {data: null, isLoading: true};
}
// from the server
componentDidMount() {
fetch('/contact').then( response => response.json()
).then( data => {
this.setState({data, isLoading: false}); // es6 syntax same as this.setState({data: data, isLoading: false})
}).catch( err => {
throw new Error(err);
});
}
render() {
const {data, isLoading} = this.state;
if(isLoading){return (<div>Loading...</div>)} //no data fetched in the initial render
return (
<div>
{data}
</div>
);
}
}
Hopefully that will help you.
Related
I found something about this bug I explained at end;
Component codes
async fetch(){ await this.$store.dispatch('bots/getBots') },
computed: { ...mapState('bots', ['bots']) },
Store codes
export const state = () => {
return {
bots: []
}
}
export const mutations = {
UPDATE_BOTS(state, bots) {
state.bots = bots
}
}
export const actions = {
getBots({commit}) {
this.$axios.$get('url', {headers: {uid: '12345'}})
.then(res => {
commit('UPDATE_BOTS',res.robots)
})
.catch(e => {
console.log(e)
})
}
}
Issue: When moving between pages via nuxt-link data loads perfectly but when I reload the page bots state is empty...
Found Issue:
I use nuxt-auth and I had one plugin for checking status of axios request that if it was 401 unauthorized I logout user if he was loggedIn, So status undefined error was from here but I commented the plugin codes and I got other error from nuxt-auth that causes that problem I had So I related that issue in other question u can see it here:
Nuxt-Auth Bug: Looks for autherization in any get request that has headers config
It is the expected behavior. Vuex state is kept in memory and when you reload the page it gets purged.
Instead of this state
export const state = () => {
return {
bots: []
}
}
try this
export const state = () => ({
bots: []
})
I am using React and request data from api, but it seems like my 'data' is getting error
My class as below:
class Login extends Component {
constructor() {
super();
this.state = {
UserName: '',
Password: '',
var:'',
}
this.Login = this.Login.bind(this);
}
Login(event) {
debugger;
api.post('/api/login', {
UserName: this.state.UserName,
Password: this.state.Password,
})
.then((result) => {
if (result.data.Status === 'Success') {
this.setState({var: result.data.status});
alert("User login Successfully");
} else {
alert('Invalid User');
}
debugger;
})
}
I am trying to make a login.
After user make a request, I will get some data from api and setState my var
The error prompt that the my result.data.Success was error. I dig some research on stack overflow, it mentioned about the Arrow Function which I used. Or is it any snytax error?
Looks like your api may result undefined as response.
So make a check on results
.then((result) => {
if (result && result.data.Status === 'Success') {
I think that result.data.data.Status is the correct way. Or you can print it with console.log(), or debugger to see what format the result is
ok this is my bad.
The overall process for my login is that my API will pass back a token after user successfully login. Later on that part, in another js of mine, which exporting default api is using interceptors from axios.
I set a gettoken function there, but at first I am processing login, so no token is stored in my frontend. As in the result, interceptions return an error -- which cause undefined
My Api code as follow:
import {Component} from 'react';
import axios from 'axios';
const instance = axios.create({
baseURL: 'http://localhost:9999/'
});
instance.interceptors.request.use(function (config) {
config.localStorgae.getItem('token');
return config;
}, function (error) {
return Promise.reject(error);
});
Basically I want to show message to user after he successfully submitted form. Like Thanks. Product added. And after few seconds I want this message to disappear.
Currently my code is pretty straightforward and contains 3 action types for AJAX request (ADD_PRODUCT_REQUEST, ADD_PRODUCT_SUCCESS, ADD_PRODUCT_FAILURE).
My component containing form connected to redux via mapDispatchToProps:
import {addProduct} from '../actions/product';
const mapDispatchToProps = dispatch => ({
onSubmit(productName) {
dispatch(addProduct(productName))
}
});
class AddProduct extends React.Component {
addProduct() {
const {onSubmit} = this.props;
onSubmit(this.productNameInput.val);
}
render() {
return (
<form onSubmit={::this.addProduct}>...</form>
)
}
}
And my action creator is also pretty straightforward (pseudocode):
export const addProduct = (name) => dispatch => {
dispatch(addProductRequest())
fetch(...).then(addProductSuccess()).catch(e => addProductFailure(error))
}
How I can using this "standard" react-redux architecture know that AJAX request executed successfully on component side?
I have only 1 idea - add some value to state informing that product was added, like added:true, but I think it's bad idea.
You must return fetch result in actions, then you need to wrap up then and catch statements to catch result of action, something like this:
addProduct() {
this.setState({ error: {}, isLoading: true });
this.props.onSubmit(this.productNameInput.val)
.then(res => this.setState({ isLoading: false, success: { title: "Success!", msg: "Product added!" } }))
.catch(err => this.setState({ isLoading: false, error: err.response.data.error} }));
}
You can bind in future this example handling to your form validation or to your frontend notification system.
Hello people of Stack Overlflow! I have a problem that I can't solve and I need your help.
My Problem: After I've sent a put request to the server nothing changes. I'm console.logging this inside of my backend console.log(ctx.request.body) and it is the same data as before the put request. Although I'm getting Status Code:200 OK in the network tab.
So, I have a form that should be able to update the data from the API. And inside of my form I have an onSubmit handler:
onSubmit={e => {
e.preventDefault()
onSubmit(id, item)
}}
Here I am calling my function handleSubmit and passing id and item. Id is the id of the object and item is the object itself.
And here's the component that uses the onSubmit:
class DoorSettingsContainer extends Component {
render() {
return (
<div>
<DoorSettingsForm
onSubmit={this.props.updateSettings}
item={this.props.location.state.item}
id={this.props.location.state.item._id}
/>
</div>
)
}
}
function mapStateToProps(state) {
return {
item: state.settings.item
}
}
function mapDispatchToProps(dispatch) {
return {
updateSettings: (id, value) => dispatch(updateSettings(id, value))
}
}
export default connect(mapStateToProps, mapDispatchToProps)(
DoorSettingsContainer
)
And here's my action that handles the put request:
export function updateSettings(id, item) {
return dispatch => {
dispatch({ type: 'SETTINGS_IS_LOADING' })
console.log(dispatch)
console.log('FÖRE', item)
axios
.put(`${settings.hostname}/locks/${id}`, item)
.then(() => {
console.log(item)
dispatch({
type: 'SETTINGS_UPDATED',
payload: {
item,
id
}
})
console.log('EFTER', item) // It's still the same
})
.catch(err => console.log(err))
}
}
And finally, my snippet from my backend:
r.put('/' + key + '/:id', async (ctx, next) => {
console.log(key) // Outputs locks
console.log(ctx.request.body) // Same as before
await ctx.db
.collection(key)
.replaceOne({ _id: objectId(ctx.params.id) }, ctx.request.body)
ctx.body = { _id: ctx.params.id }
})
So my problem is that my put request wont work to 100%. Is it might because I'm using Redux forms? Or is my backend not configured to 100%?
Thanks for all the help!
I have a route in my app that calls the mongoose method findByIdAndRemove. When I test this route in postman, I can successfully delete documents in my database, but when I call this method from my javascript file in the client, I get an error.
I getting a 404 (the response status I dictated if no document can be found). I also get an error in the terminal saying "can't set headers after they are sent." I'm not sure why I'm getting this error. Why is my route working in postman, but not when I call it from the client-side?
How should I get this working?
Here is my route on the server-side:
exports.deleteEmployee = function (req, res, next) {
const id = mongoose.Types.ObjectId(req.body.id);
Employee.findByIdAndRemove(id, (err, employee) => {
if (err) { return next(err); }
// if no employee with the given ID is found throw 400
if (!employee) { res.status(404).json('No employee with that ID'); }
res.status(200).json(employee);
});
};
Here is where I call this route from the client-side:
export const employeeDelete = ({ id }) => {
const props = { id };
return () => {
axios.delete(`${api.API_ROUTE}/employee/delete`, props)
.then(() => {
// push user back to EmployeeList and reset view stack
Actions.employeeList({ type: 'reset' });
})
.catch(err => {
console.log(err);
});
};
};
You're getting "can't set headers after they are sent." error because you're trying to respond with 200 code after having responded with 400 code.
You should surround the response statements with a if/else statement:
if (!employee) { res.status(404).json('No employee with that ID'); }
else{res.status(200).json(employee);}
It turns out the axios delete method does not take a data object, so when I passed the object called props, it never reached the server. I instead passed id as a url parameter like this:
export const employeeDelete = ({ id }) => {
return () => {
axios.delete(`${api.API_ROUTE}/employee/delete/${id}`)
.then(() => {
// push user back to EmployeeList and reset view stack
Actions.employeeList({ type: 'reset' });
})
.catch(err => {
console.log(err);
});
};
};