I initiate loading scans through this action:
export function loadPickingScans (orderReference) {
return { type: SCANNING_LOAD_SCANS, orderReference };
}
It's called in my smart (page) component:
componentDidMount() {
const { loadPickingScans } = this.props;
loadPickingScans(this.props.match.params.orderReference);
}
This is the url:
enter code herehttp://localhost:3000/orders/my-order-reference/scans
this.props.match.params.orderReference correctly contains my-order-reference.
However, adding a log to my action, orderReference is received as undefined.
What should I do to receive this expected value?
Update
By request:
function mapDispatchToProps(dispatch) {
return {
loadPickingScans: () => dispatch(loadPickingScans())
};
}
In mapDispatchToProps, while dispatching the action, you haven't passed any argument to it and hence it logs undefined in the method, you need to write it like
function mapDispatchToProps(dispatch) {
return {
loadPickingScans: (value) => dispatch(loadPickingScans(value))
};
}
or simply
const mapDispatchToProps = {
loadPickingScans
}
Related
I'm using vue 3 and composable files for sharing some functions through my whole app.
My usePluck.js composable file looks like
import { api } from 'boot/axios'
export default function usePlucks() {
const pluckUsers = ({val = null, excludeIds = null}) => api.get('/users/pluck', { params: { search: val, exclude_ids: excludeIds }})
return {
pluckUsers
}
}
In order to make use of this function in my component I do
<script>
import usePlucks from 'composables/usePlucks.js'
export default {
name: 'Test',
setup() {
const { pluckUsers } = usePlucks()
onBeforeMount(() => {
pluckUsers({excludeIds: [props.id]})
})
return {
}
}
}
</script>
So far so good, but now I'd like to even be able to not send any args to the function
onBeforeMount(() => {
pluckUsers()
})
But when I do that, I get
Uncaught TypeError: Cannot read properties of undefined (reading 'val')
I assume it's because I'm not sending an object as argument to the function, therefore I'm trying to read val from a null value: null.val
What I'm looking for is a way to send, none, only one, or all arguments to the function with no need to set null values:
// I don't want this
pluckUsers({})
// Nor this
pluckUsers({val: null, excludeIds: [props.id]})
I just want to send only needed args.
Any advice about any other approach will be appreciated.
import { api } from 'boot/axios'
export default function usePlucks() {
const pluckUsers = ({val = null, excludeIds = null} = {}) => api.get('/users/pluck', { params: { search: val, exclude_ids: excludeIds }})
return {
pluckUsers
}
}
I believe this is what you're looking for. The { ... } = {}
EDIT: It didn't work without this because with no argument the destructuring failed because it can't match an object. That's why you also need a default value on the parameter object, also called simulated named parameter.
I'm taking a test in which I should write code a in such a way that all unit test case gets passed.
Case 1:
it('should dispatch action when dispatchAction is called', async() => {
// you need to spy on store's 'dispatch' method
store = TestBed.get(Store);
spyOn(store, 'dispatch').and.callThrough();
// if you call function dispatchAction with 'movies' paramter. expect store to dispatch action='movies'
component.dispatchAction('movies');
fixture.detectChanges();
expect(store.dispatch).toHaveBeenCalledWith('movies');
});
My code:
dispatchAction($event: string) {
this.store.dispatch({type: 'movie'});
}
But the spec is getting failed throwing the below error
Expected spy dispatch to have been called with [ 'movies' ] but actual calls were [ Object({ type: 'movies' }) ].
Reducer,
export function news (state = initialState, action: Action) {
switch (action.type) {
case LOAD_SECTION_NEWS: {
return {
newsList: mockNewsList,
filter: action.type
};
}
case FILTER_SUBSECTION: {
return {
newsList: mockNewsList,
filter: action.payload
};
}
default:
return state;
}
}
export const getNewsList = (state: any) => {
return state;
};
export const getFilter = (state: any) => {
return state;
};
Action
export class NewsActions {
static LOAD_SECTION_NEWS = '[News] LOAD_SECTION_NEWS';
static FILTER_SUBSECTION = '[News] FILTER_SUBSECTION';
LoadSectionNews(list: News[]): Action {
return {
type: '',
payload: ''
};
}
FilterSubsection(subsection: string) {
return {
type: '',
payload: ''
};
}
}
How do I modify, the reducer in such a way that the unit test case get passed.
This Ngrx is out of syllabus and I've no idea. Please help.
The error reported is about .toHaveBeenCalledWith('movies'); from your test case. The expectation is the word movies to have been used as argument, and this is incorrect.
When you call this.store.dispatch({type: 'movies'}); in your controller, it is passing the object {type: 'movies'} as argument.
as your test is expecting only the word movie, it fails
change your expectation to
expect(store.dispatch).toHaveBeenCalledWith({type: 'movies'});
that will fix your test
Good luck with your studies
var data = 'movies';
this.store.dispatch(data as any)
var data = 'movies';
this.store.dispatch(data as any)
You can achieve the result by casting the string to any
I need to set some data from component to the store
methods: { // my component
...mapMutations('lists', ['setContactListName']),//import function from the store
viewHandler (id, item) { // hadler
this.$router.push(`/company/sample-contact/${id}`);
this.setContactListName(item); // pass data to the function
}
}
state() { // store
return {
contactListName: {}
};
},
mutations:{
setContactListName (state, payload) {// handler
state.contactListName = payload;
}
}
After i clicked nothing happend, even there are no errors in the console
methods: { // my component
...mapMutations(['setContactListName']), //import function from the store
viewHandler(id, item) { // hadler
this.$router.push(`/company/sample-contact/${id}`);
this.setContactListName(item); // pass data to the function
}
}
or using this.$store.commit
methods: { // my component
viewHandler(id, item) { // hadler
this.$router.push(`/company/sample-contact/${id}`);
this.$store.commit('setContactListName', item);
}
}
I have two form components, which have a common JS validator.
import { validateInput } from './validateInput.js'
export default {
data () {
return {
email: 'a#a.com',
validEmail: false
}
},
methods: {
validateInput
},
watch: {
'email': function (val) {
this.validEmail = validateInput('email', val)
// ^ makes async request
}
}
}
The validator uses jQuery.ajax - async HTTP request to server. The problem is that, since validateInput() is asynchronous, it returns before it gets a response from the server (this.validEmail is undefined)
How do I update the Vue instance (this.validEmail) after the async request in this JS imported function is completed?
In simple terms - how do I access the Vue instance from inside validateInput in a way that works asynchronously?
I've tried passing the Vue instance as an argument, doesn't update:
validateInput('email', val, this)
----
// validateInput.js
email() {
$.ajax({
...
success(response) {
vueInstance.validEmail = response // doesn't work
}
})
vueInstance.validEmail = false
// ^^^^ this works
}
Try this
watch: {
'email': function (val) {
validateInput('email', val,this)
}
}
and
validateInput('email', val, ref)
----
// validateInput.js
email() {
$.ajax({
...
success(response) {
ref.validEmail = response // doesn't work
}
})
// ^^^^ this works
}
Or the traditional way to deal with asynchronous calls is pass a callback that has a closure over the variable that needs edited.
watch: {
'email': function (val) {
validateInput('email', val,function(response){this.validEmail=response})
}
}
//...
validateInput('email', val, cb)
//...
success(response) {
cb(response);
}
I can successfully upload to firebase storage and retrieve image URL using promises, but I wanted to link a progress bar to the percent completion of the upload. What I have achieved thus far: When I call this function from a component:
this.props.handleNewPrizeImageUpload(this.progressCallback, this.imageUploadCompletionCallback, prizeImage)
with these callbacks defined in the component:
progressCallback (progress) {
**//this.someOtherFunction(progress).bind(this)**
return console.log('Upload is ' + progress + '% done')
}
imageUploadCompletionCallback (url) {
**//this.props.someOtherFunctionB(url)**
console.log('SAVEPRIZEIMAGE RAN SUCCESFULLY RETURN URL : ', url)}
this function runs:
export function handleNewPrizeImageUpload (progressCallback, imageUploadCompletionCallback,
prizeImage) {
savePrizeImage(progressCallback, imageUploadCompletionCallback,prizeImage)
}
The savePrizeImage is a function that save the image and runs callback back functions accordingly.
I can successfully retrieve the progress value and the URL Data but the Problem I am facing is that I can't use my other defined function within those callbacks to do something the retrieved Data, I keep getting the error that this is not defined. I have tried bind(this) it does not work.
error:
Uncaught TypeError: Cannot read property 'someOtherFunction' of
undefined
What I have tried:
constructor (props) {
super(props)
this.someOtherFunction = this.someOtherFunction.bind(this)
}
and then calling it like so:
progressCallback (progress) {
console.log('Upload is ' + progress + '% done')
this.someOtherFunction(progress)
}
someOtherFunction (progress) {
console.log('HAHAHA')
}
Heer is the Entire component Code Block:
import React, { Component, PropTypes } from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import {CreatePrizeForm} from 'components'
import * as ActionCreators from 'redux/modules/prizes'
export class CreatePrizeFormContainer extends Component {
static contextTypes = {
router: PropTypes.object.isRequired
}
constructor (props) {
super(props)
// this.someOtherFunction = this.someOtherFunction.bind(this)
// this.progressCallback = this.progressCallback.bind(this)
}
handlePrizeData (prizeImage) {
this.props.handleNewPrizeImageUpload(this.progressCallback, this.imageUploadCompletionCallback, PrizeImage)
}
progressCallback (progress) {
console.log('Upload is ' + progress + '% done')
//this.someOtherFunction(progress)
}
imageUploadCompletionCallback (url) {
console.log('SAVE TO FIREBASE RAN SUCCESFULLY RETURNED IMAGE URL : ', url)
}
someOtherFunction (progress) {
console.log('HAHAHA')
}
render () {
return (
<div>
<CreatePrizeForm addPrizeData = {(prizeImage) => { this.handlePrizeData(prizeImage) }}/>
</div>
)
}
}
function mapStateToProps (state, props) {
return {
}
}
function mapDispatchToProps (dispatch, props) {
return bindActionCreators(ActionCreators, dispatch)
}
export default connect(mapStateToProps, mapDispatchToProps)(CreatePrizeFormContainer)
When you pass a reference to a function (e.g. as argument, or other assignment), it will not have its context bound to it.
This is the case with the this.progressCallback argument:
this.props.handleNewPrizeImageUpload(this.progressCallback, ... )
That progressCallback argument variable is not linked to this, even though you pass it like that -- which is the cause of a lot of misunderstanding; you are not the only one.
Solve it as follows:
this.props.handleNewPrizeImageUpload(this.progressCallback.bind(this), ... )
See the very good Q&A on this.
Here is some of your code trimmed down to a working snippet:
"strict"
// Dummy Component class for this snippet only
class Component { constructor (props) { this.props = props } }
// Your class:
class CreatePrizeFormContainer extends Component {
constructor (props) { super(props) }
handlePrizeData (prizeImage) {
this.props.handleNewPrizeImageUpload(
this.progressCallback.bind(this),
this.imageUploadCompletionCallback.bind(this), prizeImage)
}
progressCallback (progress) {
console.log('Upload is ' + progress + '% done')
this.someOtherFunction(progress)
}
imageUploadCompletionCallback (url) {
console.log('SAVE TO FIREBASE RAN SUCCESFULLY RETURNED IMAGE URL : ', url)
}
someOtherFunction (progress) { console.log('HAHAHA') }
}
// Dummy savePrizeImage function for this snippet only
function savePrizeImage(progressCallback, imageUploadCompletionCallback, ImageFile) {
// Simulate two progress events
setTimeout(function() { progressCallback(50) }, 0)
setTimeout(function() { progressCallback(100) }, 500)
setTimeout(function() { imageUploadCompletionCallback('http://example.com') }, 510)
}
// Create instance, passing simple prop literal
var obj = new CreatePrizeFormContainer({
handleNewPrizeImageUpload: function(progressCallback,
imageUploadCompletionCallback, ImageFile) {
savePrizeImage(progressCallback, imageUploadCompletionCallback, ImageFile)
}
})
obj.handlePrizeData('dummyPrizeImage.img') // Call handlePrizeData