i am making vue application i want to add more data which is fetching through laravel return in array without loosing old data
my methods is
getData () {
axios.get('get/users')
.then(response => {
this.queue = response.data.users
})
.catch(e => {
this.errors.push(e)
})
}
and my data
data: function () {
return {
queue: []
}
},
Full Script is
data: function () {
return {
queue: []
}
},
created () {
this.getData()
},
methods: {
getData () {
axios.get('get/users')
.then(response => {
this.queue = response.data.users
})
.catch(e => {
this.errors.push(e)
})
},
decide (choice) {
this.$refs.tinder.decide(choice)
},
submit (choice) {
switch (choice) {
case 'nope': // 左滑
break;
case 'like': // 右滑
break;
case 'super': // 上滑
break;
}
if (this.queue.length < 2) {
this.getData()
}
}
}
here is video link
https://youtu.be/iv82EGMD4XA
i want when queue have 2 data left trigger this.getData()
fetch users and add array data to queue without loosing old queue data
You can use the concat function
this.queue = this.queue.concat(response.data.users);
In the axios response
Instead of the
this.queue = response.data.users
Related
Configured my store this way with redux toolkit for sure
const rootReducer = combineReducers({
someReducer,
systemsConfigs
});
const store = return configureStore({
devTools: true,
reducer: rootReducer ,
// middleware: [middleware, logger],
middleware: (getDefaultMiddleware) => getDefaultMiddleware({ thunk: false }).concat(middleware),
});
middleware.run(sagaRoot)
And thats my channel i am connecting to it
export function createSocketChannel(
productId: ProductId,
pair: string,
createSocket = () => new WebSocket('wss://somewebsocket')
) {
return eventChannel<SocketEvent>((emitter) => {
const socket_OrderBook = createSocket();
socket_OrderBook.addEventListener('open', () => {
emitter({
type: 'connection-established',
payload: true,
});
socket_OrderBook.send(
`subscribe-asdqwe`
);
});
socket_OrderBook.addEventListener('message', (event) => {
if (event.data?.includes('bids')) {
emitter({
type: 'message',
payload: JSON.parse(event.data),
});
//
}
});
socket_OrderBook.addEventListener('close', (event: any) => {
emitter(new SocketClosedByServer());
});
return () => {
if (socket_OrderBook.readyState === WebSocket.OPEN) {
socket_OrderBook.send(
`unsubscribe-order-book-${pair}`
);
}
if (socket_OrderBook.readyState === WebSocket.OPEN || socket_OrderBook.readyState === WebSocket.CONNECTING) {
socket_OrderBook.close();
}
};
}, buffers.expanding<SocketEvent>());
}
And here's how my saga connecting handlers looks like
export function* handleConnectingSocket(ctx: SagaContext) {
try {
const productId = yield select((state: State) => state.productId);
const requested_pair = yield select((state: State) => state.requested_pair);
if (ctx.socketChannel === null) {
ctx.socketChannel = yield call(createSocketChannel, productId, requested_pair);
}
//
const message: SocketEvent = yield take(ctx.socketChannel!);
if (message.type !== 'connection-established') {
throw new SocketUnexpectedResponseError();
}
yield put(connectedSocket());
} catch (error: any) {
reportError(error);
yield put(
disconnectedSocket({
reason: SocketStateReasons.BAD_CONNECTION,
})
);
}
}
export function* handleConnectedSocket(ctx: SagaContext) {
try {
while (true) {
if (ctx.socketChannel === null) {
break;
}
const events = yield flush(ctx.socketChannel);
const startedExecutingAt = performance.now();
if (Array.isArray(events)) {
const deltas = events.reduce(
(patch, event) => {
if (event.type === 'message') {
patch.bids.push(...event.payload.data?.bids);
patch.asks.push(...event.payload.data?.asks);
//
}
//
return patch;
},
{ bids: [], asks: [] } as SocketMessage
);
if (deltas.bids.length || deltas.asks.length) {
yield putResolve(receivedDeltas(deltas));
}
}
yield call(delayNextDispatch, startedExecutingAt);
}
} catch (error: any) {
reportError(error);
yield put(
disconnectedSocket({
reason: SocketStateReasons.UNKNOWN,
})
);
}
}
After Debugging I got the following:
The Thing is that when I Provide one Reducer to my store the channel works well and data is fetched where as when providing combinedReducers I am getting
an established connection from my handleConnectingSocket generator function
and an empty event array [] from
const events = yield flush(ctx.socketChannel) written in handleConnectedSocket
Tried to clarify as much as possible
ok so I start refactoring my typescript by changing the types, then saw all the places that break, there was a problem in my sagas.tsx.
Ping me if someone faced such an issue in the future
app.js
const mapStateToProps = (state) => {
return {home:state}
}
const mapDispatchToProps = (dispatch) => {
return {
guestLogin: (data)=>{dispatch(guestLogin(data)).then(()=>{
dispatch(initiateTrans(stateProps.home))
})},
};
}
const mergeProps = (stateProps, dispatchProps, ownProps) => {
return Object.assign({}, ownProps, stateProps, dispatchProps,{
initiateTrans: () => dispatchProps.initiateTrans(stateProps.home),
})
}
Action.js
export const guestLogin= (state)=>{
var data={
'email':state.email,
'name':state.name,
'phone_number':state.ph_number,
'phone_code':state.country_code
}
return function(dispatch) {
return dataservice.guestSignup(data).then(res => {
dispatch(afterLoggedGuest(res))
}).catch(error => {
throw(error);
});
}
}
function afterLoggedGuest(result) {
return {type: guestLoginChange, result};
}
export const initiateTrans= (updatedState)=>{
return function(dispatch) {
return dataservice.initiateTransaction(updatedState).then(res => {
console.log("initiateTransaction",res)
}).catch(error => {
throw(error);
});
}
}
Reducer.js
if(action.type === guestLoginChange){
return {
...state,guestData: {
...state.guestData,
Authorization: action.result.authentication ,
auth_token: action.result.auth_token ,
platform: action.result.platform
} ,
}
}
I am having two api requests.. After first api request success i want to update state value then pass that updated state to another api request..
I tried to get the updted props
how to dispatch the initiateTrans with update props
I need to update value at api request success in call back i need to call one more request with updated state value
currently i am not able to get the update props value
I think this is a good use case for thunk (redux-thunk), which is a middleware that allows you to execute multiple dispatches in an action.
You will need to apply the middleware when you configure the initial store (see docs on link above). But then in your actions, you can wrap the code with a dispatch return statement, which gives you access to multiple calls. For example:
export const guestLogin= (state)=>{
return dispatch => {
var data={...} // some data in here
return dataservice.guestSignup(data).then(res => {
dispatch(afterLoggedGuest(res))
}).catch(error => {
throw(error);
// could dispatch here as well...
});
}
}
I set an empty array inside a state
const state = {
jobs: []
}
Inside the component, I dispatch an action and the code looks like this:
created(){
this.$store.dispatch('viewJobs');
}
The viewJobs actions looks like the following:
viewJobs: ({commit}) => {
axios.get('/api/jobs')
.then(res => {
const jobss = res.data;
console.log(jobss);
commit('LIST_JOBS', jobss);
})
.catch(error => console.log(error));
}
And then the mutations looks like this:
'LIST_JOBS'(state, jobss){
state.jobs.push(jobss);
}
From the laravel side, my controller looks like this:
$jobs = Employment::all();
return $jobs->toJson(JSON_PRETTY_PRINT);
When I load the page, am able to console log jobss, but the state does not get updated.
How can I successfully push the data to the state?
You are adding the entire array as a single element of state.jobs. Instead, you can use the Javascript spread operator, to push each element from the array:
state.jobs.push(...jobss)
Try to use response()->json()
return response()->json(Employment::all(),200);
and try use {jobss:jobss} in commit section
viewJobs: ({commit}) => {
axios.get('/api/jobs')
.then(res => {
const jobss = res.data;
console.log(jobss);
commit('LIST_JOBS', {jobss:jobss});
})
.catch(error => console.log(error));
}
Another way, your vuex store looks like this
// state
export const state = () => ({
items: []
})
// getters
export const getters = {
items: state => state.items
}
// mutations
export const mutations = {
SET_ITEMS (state, { items }) {
state.items = items
},
PUSH_ITEM (state, { item }) {
state.items.push(item)
},
UPDATE_ITEM (state, { index, item }) {
state.items[index] = item
},
DELETE_ITEM: (state, index) => {
state.items.splice(index.index, 1);
}
}
// actions
export const actions = {
setItems ({ commit }, { items }) {
commit('SET_ITEMS', { items })
},
pushItem ({ commit,state }, { item }) {
commit('PUSH_ITEM', { item })
},
deleteItem ({ commit,state }, { index }) {
commit('DELETE_ITEM', { index })
},
updateItem ({ commit,state }, { index,item }) {
commit('UPDATE_ITEM', { index,item })
},
}
Then in your component call your action
this.$axios.$get('/api/jobs')
.then(res => {
const jobss = res.data;
console.log(jobss);
this.$store.dispatch('your_store_name/setItems', {items:jobss});
})
.catch(error => console.log(error));
In the code below I want to get the form values from Edit form and sent using fetch on handleClick.
class GenerateButton extends Component {
handleClick = () => {
const { push, record, showNotification, values } = this.props;
const updatedRecord = { ...record, is_approved: true };
fetch(`api/reports/${record.id}`, { method: 'GET', body: updatedRecord })
.then((response) => {
return response.blob();
}).then(function(blob) {
console.log(blob);
})
.catch((e) => {
showNotification('Error: report generation failed.', 'warning')
});
}
render() {
return <RaisedButton label="Generate" onClick={this.handleClick} />;
}
}
I saw a similar question here which doesnt solve my problem. I am trying to run a cron job every 10 hours that lets me get the categories first and then based on the categories, i find the information for each category. How can I simplify the below Promise. I am NOT using Bluebird or Q, this is the native JS promise. Honestly, the code below looks like the same callback hell Promises were supposed to avoid, any suggestions
flipkart.getAllOffers = function () {
interval(43200, () => {
flipkart.findAllCategories()
.then((categories) => {
flipkart.save('flipkart_categories.json', categories)
if (categories) {
for (let item of categories) {
flipkart.findAllForCategory(item.category, item.top)
.then((items) => {
flipkart.save('flipkart_top_' + item.category + '.json', items)
}).catch((error) => {
console.log(error)
})
}
}
})
.catch((error) => {
console.log(error)
})
})
}
function interval(seconds, callback) {
callback();
return setInterval(callback, seconds * 1000);
}
If you stop using an extra level of indent just for .then(), then you have a pretty simple structure.
One .then() handler that contains
an if() statement
that contains a for loop
that contains another async operation
In this modified version, half your indent comes from your if and for which has nothing to do with promises. The rest seems very logical to me and doesn't at all look like callback hell. It's what is required to implement the logic you show.
flipkart.getAllOffers = function () {
interval(43200, () => {
flipkart.findAllCategories().then((categories) => {
flipkart.save('flipkart_categories.json', categories)
if (categories) {
for (let item of categories) {
flipkart.findAllForCategory(item.category, item.top).then((items) => {
flipkart.save('flipkart_top_' + item.category + '.json', items)
}).catch((error) => {
console.log(error)
throw error; // don't eat error, rethrow it after logging
});
}
}
}).catch((error) => {
console.log(error)
})
})
}
If flipkart.save() is also async and returns a promise, then you probably want to hook those into the promise chain too.
You can always create a helper function that may improve the look also like this:
flipkart.getAllOffers = function () {
interval(43200, () => {
flipkart.findAllCategories().then(iterateCategories).catch((error) => {
console.log(error);
})
})
}
function iterateCategories(categories) {
flipkart.save('flipkart_categories.json', categories);
if (categories) {
for (let item of categories) {
flipkart.findAllForCategory(item.category, item.top).then((items) => {
flipkart.save('flipkart_top_' + item.category + '.json', items);
}).catch((error) => {
console.log(error);
});
}
}
}
If you're trying to collect all the results (something your title implies, but your question doesn't actually mention), then you can do this:
flipkart.getAllOffers = function () {
interval(43200, () => {
flipkart.findAllCategories().then(iterateCategories).then((results) => {
// all results here
}).catch((error) => {
console.log(error);
});
})
}
function iterateCategories(categories) {
flipkart.save('flipkart_categories.json', categories);
let promises = [];
if (categories) {
for (let item of categories) {
let p = flipkart.findAllForCategory(item.category, item.top).then((items) => {
flipkart.save('flipkart_top_' + item.category + '.json', items);
}).catch((error) => {
console.log(error);
});
promises.push(p);
}
}
// return promise here that collects all the other promises
return Promise.all(promises);
}