I am trying to bring the error messages from the backend to the frontend using the MERN stack. I am able to receive the error messages in the developer tools, but not able to show the messages in the UI. I am using Redux for the state manager. The console.log() in my concomponentDidUpdate is not working when I am submitting the form. Can someone please clarify what is wrong with my code?
state = {
name: '',
email: '',
phoneNo: null,
dateOfBirth: new Date,
gender: 'Select',
education: '',
checkBox: false,
msg: null
}
static propTypes = {
addInfo: PropTypes.func.isRequired,
info: PropTypes.object.isRequired,
error: PropTypes.object.isRequired
}
componentDidUpdate(prevProps, nextProps) {
const { error } = this.props;
if (error !== nextProps.error) {
console.log("Working");
if (error.id === 'REGISTER_FAIL')
this.setState({ msg: error.msg.msg });
else
this.setState({ msg: null });
}
}
componentDidUpdate() will not be invoked in initial mount and will only be called during component rerenders.
If you need it to be called in initial mount as well as subsequent updates, either duplicate it to componentDidMount or use static getDerivedStateFromProps
Following this docs, componentDidUpdate receive 3 params: prevProps, prevState and snapshot.
In your code, you used it like the next props:
componentDidUpdate(prevProps, nextProps)
It should be something like:
componentDidUpdate(prevProps, prevState){
const { error } = this.props;
// React will call didUpdate after component is updated
// this.props is the nextProps.error as you trying to do
if (error !== prevProps.error) {
console.log("Working");
if (error.id === 'REGISTER_FAIL')
this.setState({ msg: error.msg.msg });
else
this.setState({ msg: null });
}
}
Or you will want to use UNSAFE_componentWillReceiveProps
UNSAFE_componentWillReceiveProps(nextProps){}
Related
I am trying to use the class-validator #ValidateIf conditional validator decorator based on the value of a environment variable. Let me share the code for better understanding:
// .env file entry
AMOUNT_CHECK_IN_MODE=TEST
In my validator(.dto) file, i have the following code placed
import {
IsNumberString,
Max,
ValidateIf
} from 'class-validator';
export class GtTransactionDto {
otherProperty: string;
constructor() {
this.otherProperty = process.env.AMOUNT_CHECK_IN_MODE;
}
#ValidateIf(o => o.otherProperty === 'TEST')
#Max(1, {
message: 'Amount should not exceed 1',
context: {
code: GtTransactionErrorCode.validate.DestinationAmount
},
})
#ValidateIf(o => o.otherProperty === 'LIVE')
#IsNumberString(
{},
{
message: 'This is not a valid $property number',
context: {
code: GtTransactionErrorCode.validate.DestinationAmount,
},
}
)
#ValidateIf(o => o.otherProperty === 'TEST')
#IsNumberString(
{},
{
message: 'This is not a valid $property number',
context: {
code: GtTransactionErrorCode.validate.DestinationAmount,
},
}
)
destinationAmount!: string;
}
I want to make sure that in the if TEST is set as the value of AMOUNT_CHECK_IN_MODE in .env file, then the validation for max amount and isNumberString should run. However if the value is set to LIVE then only validation for isNumberString should run
Any help would be highly appreciated
You could use Validation groups and set the group based on the environment variable.
From the docs
import { validate, Min, Length } from 'class-validator';
export class User {
#Min(12, {
groups: ['registration'],
})
age: number;
#Length(2, 20, {
groups: ['registration', 'admin'],
})
name: string;
}
let user = new User();
user.age = 10;
user.name = 'Alex';
validate(user, {
groups: ['registration'],
}); // this will not pass validation
validate(user, {
groups: ['admin'],
}); // this will pass validation
validate(user, {
groups: ['registration', 'admin'],
}); // this will not pass validation
validate(user, {
groups: undefined, // the default
}); // this will not pass validation since all properties get validated regardless of their groups
validate(user, {
groups: [],
}); // this will not pass validation, (equivalent to 'groups: undefined', see above)
Here is the request type:
interface IgetProductsByGenderRequest extends express.Request {
readonly params: Readonly<{ gender: string; }>;
}
When I'm using req.params.gender I get undefined.
When I'm using req.params I get the param but in object and I want to get it in a var.
My backend controller:
const getProductsByGender = async (
req: IgetProductsByGenderRequest,
res: IgetProductsByGenderResponse
) => {
console.log(req.params)
ServerGlobal.getInstance().logger.info(
`<getProductsByGender>: Start processing request filtered by and gender ${req.params.gender}`
);
if (
!ServerGlobal.getInstance().isValidGenderValue(+req.params.gender)
) {
ServerGlobal.getInstance().logger.error(
`<getProductsByGender>: Failed to get products because of invalid gender filtered by gender ${req.params.gender}`
);
res.status(400).send({
success: false,
message: "Please provide valid gender",
});
return;
}
try {
const products = await ProductDB.find({ gender: +req.params.gender });
ServerGlobal.getInstance().logger.info(
`<getProductsByGender>: Successfully got the products filtered by gender ${req.params.gender}`
);
res.status(200).send({
success: true,
message: "Successfully retrieved products",
data: products.map((product) => ({
id: product.id as string,
gender: {
value: product.gender,
label: ServerGlobal.getInstance().getGenderLabel(product.gender)!,
},
title: product.title,
description: product.description,
price: product.price,
imageFilename: product.imageFilename,
})),
});
return;
} catch (e) {
ServerGlobal.getInstance().logger.error(
`<getProductsByGender>: Failed to get products filtered by gender ${req.params.gender} because of server error: ${e}`
);
res.status(500).send({
success: false,
message: "Server error",
});
return;
}
};
How can I access the gender param?
I suggest reading the documentation regarding routing and regarding query parameters.
You have req.query, which is for query parameters, e.g. /some/path?myVariable=test would have req.query.myVariable === 'test'.
You also have req.params which is when you're using URL parameters, e.g. /some/path/:id would have req.params.id === 'test' when the user visits /some/path/test.
Make sure you are using/accessing the correct one, as it's easy to make mistakes in this regards. And of course watch out for typos, although you should've spotted that with your console.log(req.params) statement.
I'm making app with MEAN stack and I want on every get request to increase viewCounter on specific document ( Property ) inside collection.
If i put this code inside get request of requested property
Property.findByIdAndUpdate('id', { $inc: { counter: 1 } }, {new: true})
It will increase loading of data and i want to do that after user gets his data.
So is the best way to do this just to send additional request to the database after initial data is loaded ?
Property {
name: '',
description: '',
...,
viewCounter: 5
}
exports.getProperty = catchAsync(async (req, res, next) => {
query = await Property.findById(req.params.id).lean();
if(!query) {
return next(new AppError('No property found with that ID', 404))
}
res.status(200).json({
status: 'success',
data: {
query
}
})
})
Node events can be used to keep the counter of events.
Official document
Reference for code
eventEmitter.on('db_view', ({ parameters }) => {
eventTracker.track(
'db_view',
parameters
);
})
eventEmitter.on('db_view', async ({ user, company }) => {
Property.findByIdAndUpdate('id', { $inc: { counter: 1 } }, {new: true})
})
Try to send request after making sure your document has loaded.
angular.element($window).bind('load', function() {
//put your code
});
i can't find a way to test form yup validation:
it('displays error on submit if name is empty', async () => {
const wrapper = mount(<MyFormik/>)
const getForm = () => wrapper.find('form')
wrapper.find('input[name="name"]').simulate('change', {
persist: () => {},
target: {
name: 'name',
value: ''
}
})
wrapper
.find('MyInnerForm')
.props()
.submitForm()
await wait(0) // await next tick or even 1s...
wrapper.update()
expect(
wrapper
.update()
.find('.error')
.exists()
)
.toBeTruthy() // FALSE!
})
No matter if i wait after submit, update wrapper errors prop is always empty.
And the solution here are not working for me:
https://github.com/jaredpalmer/formik/issues/1146
https://github.com/jaredpalmer/formik/issues/110
Looks like wrapper won't update
Here's the log of formik props after submit:
{ errors: {},
label: '',
name: 'name',
type: 'text',
values: { name: '' },
touched: { name: true },
isValidating: false,
status: undefined,
initialValues: { name: '' },
validateOnChange: true,
validateOnBlur: true } }
...
submitCount: 1,
isValid: false,
You can validate the form values directly on your validation schema.
const yup = require('yup')
const contactSchema = yup.object({
name: yup.string()
.required(),
age: yup.number()
.required()
.positive()
.integer()
})
const errors = await contactSchema.validate({
name: 'Kenneth',
age: -35.5
}).catch(function(err) {
return err
});
console.log("errors", errors);
https://runkit.com/kluplau/5defa8cd122cf6001a3034c7
Without seeing your component I'm not entirely sure what's going wrong. This is likely not to be working:
wrapper
.find('MyInnerForm')
.props()
.submitForm()
If your component MyInnerForm contains a Formik form calling submitForm() there will not cause Formik's validation to run. I would instead do something like this:
wrapper.find("form").simulate("submit");
However if that isn't solving your issue I made a full example that you can have a look at here.
In Laravel 5.4 I am trying to make a payment with Stripe. I am following the video on laracast if you have an account you can watch the video here:
https://laracasts.com/series/how-to-accept-payments-with-stripe/episodes/3
I changed it up to fit my needs and there are somethings he does that does not work with version 0.3 of vue which I was able to fix except for this problem.
I have this code:
data: function data() {
return {
stripeEmail: '',
stripeToken: ''
};
},
created: function created() {
this.stripe = StripeCheckout.configure({
key: "my_key",
image: "https://stripe.com/img/documentation/checkout/marketplace.png",
locale: "auto",
token: (token) => {
this.stripeToken = token.id;
this.stripeEmail = token.email;
this.$http.post('/payment', this.$data).then(response => alert('Message'));
}
});
},
methods: {
buy: function buy() {
this.stripe.open({
name: "One Month Subscription",
description: "Having your business displayed for one month.",
zipcode: true,
amount: 1000
});
}
}
I am able to put the information in but as soon as I hit submit it returns the error:
Uncaught TypeError: Cannot read property 'post' of undefined
I installed vue-resource in my bootstrap.js here:
window.Vue = require('vue');
require('vue-resource');
This solved the $http problem but now I get the post problem.
If there is any other information you need let me know.
I think there might be a problem with this. Specifically, the this in created is likely not the same as the this in token. Try ... this:
created: function created() {
var self = this;
self.stripe = StripeCheckout.configure({
key: "my_key",
image: "https://stripe.com/img/documentation/checkout/marketplace.png",
locale: "auto",
token: (token) => {
self.stripeToken = token.id;
self.stripeEmail = token.email;
self.$http.post('/payment', self.$data).then(response => alert('Message'));
}
});
},
I know you're using arrow functions so this shouldn't be the case, but I'd give it a try anyways and see how it goes.