how to get data with mapActions - vue.js

I can't seem to get the data I need using mapActions from my store. I am doing an Axios GET (I turn that data to an array), and pass that data to my home.vue, and render a list of notes.
Now, it works fine if I use mapGetters, but to my understanding, I can access data directly from mapActions, I've seen people do it, but so far I can't. Or can I?
Home.vue:
export default {
methods:{
// Not Working
...mapActions(
['getNotes']
),
created(){
// Not working
this.getNotes()
console.log(this.getNotes())//returns pending Promise
}
}
my store.js
export default new Vuex.Store({
state: {
...other stuff in state...
// this is getting the notes from firebase
notes: {}
},
getters: {
...other getters...
notes: state => state.notes
},
mutations: {
...other mutations...
SET_NOTES (state, notes) {
state.notes = notes
}
},
actions: {
getNotes ({ commit }) {
axios.get('/data.json')
.then(res => {
const incoming = res.data
const notes = [] // <-- this is commited ok without explicit return
// converting object to array
// extracting firebase ids for manipulating existing notes
for (let key in incoming) {
const note = incoming[key]
note.id = key
notes.push(note)
}
console.log(notes)
commit('SET_NOTES', notes)
// return notes <-- tried that, no effect!
})
.catch((error) => {
console.log('Error: ', error)
})
},
...commiting 2 other things needed for my app
}
...other actions...
})

I don't see you have return the notes data as a return value inside your action getNotes(). At the end of your success callback all you did is commit your data into the notes commit('SET_NOTES', notes).
Return your notes data
getNotes ({ commit }) {
axios.get('/data.json')
.then(res => {
const incoming = res.data
const notes = []
// converting object to array
// extracting firebase ids for manipulating existing notes
for (let key in incoming) {
const note = incoming[key]
note.id = key
notes.push(note)
// array.reverse()
}
console.log(notes)
commit('SET_NOTES', notes)
// HERE YOU RETURN YOUR NOTES DATA
return notes
})
.catch((error) => {
console.log('Error: ', error)
})
}

Related

strange console.log output with vuex

i have some simple vuex store with
const state = {
todos : []
}
const getters = {
allTodos: (state) => state.todos
}
const actions = {
async fetchTodos({ commit }) {
console.log(this.state.todos)
if(state.todos.length == 0) {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos?_limit=5')
commit('setTodos', response.data)
}
}
}
const mutations = {
setTodos(state, todos) {
state.todos = todos
}
}
why does console.log in fetchTodos action output populated todos before it was populated with axios.get and setTodos mutation?
when i write
const actions = {
fetchTodos({ commit }) {
console.log(this.state.todos)
setTimeout(async () => {
if(state.todos.length == 0) {
const response = await axios.get('https://jsonplaceholder.typicode.com/todos?_limit=5')
commit('setTodos', response.data)
}
}, 10000)
}
}
output is normal with empty todos in state
That's because you will see a little blue triangle right next to the console log. I don't know the technical term for it but what happens is that the browser will update that variable with the current value because it is a reactive variable and since it is a reference being pointed to a location in memory, it will update.
If you truly wish to see the value and prove what was described above, you can write:
console.log(JSON.parse(JSON.stringify(this.state.todos)));

react-native-storage returning undefined from local storage

I am having some difficulties on executing local storage operations...
"react-native": "0.64",
"react-native-storage": "^1.0.1"
I'm using react-native-storage, as pointed in title, and I have created two simple methods for handling Writing and Reading:
import Storage from 'react-native-storage';
import AsyncStorage from '#react-native-community/async-storage';
const storage = new Storage({
size: 1000,
storageBackend: AsyncStorage,
defaultExpires: null,
enableCache: true,
sync: {
return: 'No data.'
}
});
const saveToLocalStorage = (key: any, data: any) => {
storage.save({
key,
data,
expires: null
})
}
const getFromLocalStorage = (key: any) => {
storage.load({
key,
autoSync: true
})
.then(data => {
return { data }
})
.catch(err => { });
}
export { saveToLocalStorage, getFromLocalStorage }
As you can see, it's pretty much the code example from https://www.npmjs.com/package/react-native-permissions.
At the App.tsx file, I do the following:
useEffect(() => {
saveToLocalStorage('test', 'test data');
const test = getFromLocalStorage('test');
}, [])
which returns undefined.
But if in the method getFromLocalStorage I replace
.then(data => {
return { data }
})
for
.then(data => console.warn(data));
the result is the image from bellow:
In short:
If the function returns the object from the storage, it brings undefined.
If the function returns a console.log from the storage, it brings what I've written on it.
because return { data } is not a valid expression for async functions
just use AsyncStorage, react-native-storage is not needed unless you develop for both mobile and web
useEffect(() => {
await AsyncStorage.setItem('test', 'myValue');
const value = await AsyncStorage.getItem('test');
console.log(value);
}, [])

What is the best practice for updating the local variables in redux-thunk after getting the response from api?

I have implemented the redux-thunk which works just fine in my react-native application. I have some 'this.counterValue', which value must be updated after getting the response from the api. As api fetch methods are implemented in another actions files, and response is achieved in that file. So, how must it be implemented to make this work fine.I don't want the change in 'this.counterValue' results in re-render of my application. I am new to react native, it would be great to be helped. Thanks.
Component file:
this.counterValue = 75; //local variable
this.props.fetchData('onStart'); // call to fetch data from actions files
Action file:
export const fetchData = (fetchType) => {
return async dispatch => {
dispatch(fetchingDataRequest());
fetch(AllApi),
{
method: 'GET',
headers:
{
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer '+ global.apiToken,
},
})
.then(response => {
return response.json()
})
.then(RetrivedData => {
dispatch(fetchingDataSuccess(RetrivedData.data));
})
.catch(error => {
dispatch(fetchingNotificationFailure(error));
});
}
}
using dispatch send the data to the reducer and in reducer update the state value which then you could use it in the component.
Reducer
import { reducerWithInitialState } from 'typescript-fsa-reducers'
import { DemoListViewActions } from './Actions'
export interface DemoListViewState {
data: any[]
selectedData: any
}
const initialState: DemoListViewState = {
data: [],
selectedData: undefined
}
const dataListRequestSuccessHandler = (state: DemoListViewState, payload: any[]): DemoListViewState => {
return {
...state,
data: payload
}
}
export const DemoListViewReducer = reducerWithInitialState(initialState)
.case(DemoListViewActions.dataListRequestSuccess, dataListRequestSuccessHandler)
.build()
Container
const mapStateToProps: MapStateToProps<IDemoListViewStateProps, OwnProps, RootState> = (state: RootState, ownProps: OwnProps) => {
const {data} = state.demoListView
return {
listData: data
}
}
Component
export interface IDemoListViewStateProps {
listData: any[]
}
just store it in props and state and you could manipulate it easily
After dispatching your action,you have to update your reducer
Import Action from './Action'
const initialState = {
people :[ ] // initiate empty array
}
export default function(state=initialState,action){
switch(action.type){
case Action.test:
return testUpdate(state,action)
default :
return state
}
}
//Update the result from the api,people array will be populated
with latest data
function testUpdate(state,action){
return {...state,people:action.payload.people}
}

get single record through axios in vuex store

I would like to return a single record from my back end using a Vuex store module in Nuxt.
I have the following in my component, which passes the value i want
( which is the $route.params.caseId )
created () {
this.$store.dispatch('cases/getCase', $route.params.caseId );
},
I pass the $route.params.caseId into my getCase action in my vuex store module as follows
getCase ({ commit, context }, data) {
return axios.get('http' + data + '.json')
.then(res => {
const convertcase = []
for (const key in res.data) {
convertcase.push({ ...res.data[key], id: key })
}
//console.log(res.data) returns my record from firebase (doesnt display the key though in the array, just the fields within the firebase record, but assume this is expected?
commit('GET_CASE', convertcase)
})
.catch(e => context.error(e));
},
the convert case is to extract the id from firebase key and add it to my array as id field (Is this correct for a single result from firebase in this way?)
My mutation
// Get Investigation
GET_CASE(state, caseId) {
state.caseId = caseId;
},
Now when I use Case Name: {{ caseId.case_name }} I'm not getting any result,
I'm not getting an error though, any thoughts on what i am doing wrong please
Many Thank
You can pass more data to an action like you did in the dispatch method and later access them normally.
Note the data parameter of the getCase function, in your example data === $route.params.caseId
//Load single investigation
getCase ({ commit, context }, data) {
return axios.get('http' + investigationID + '.json')
.then(res => {
const convertcase = []
for (const key in res.data) {
convertcase.push({ ...res.data[key], id: key })
}
commit('GET_CASE', convertcase)
})
.catch(e => context.error(e));
},
In case you want to use promises, check out the exemple below of a action in my app that fetches a single BLOG_POST
let FETCH_BLOG_POST = ({commit, state}, { slug }) => {
return new Promise((resolve, reject) => {
fetchBlogPost(slug, state.axios)
.then((post) => {
console.log("FETCH_BLOG_POSTS", post.data.data)
commit('SET_BLOG_POST', post.data.data)
resolve(post.data)
})
.catch((error) => {
console.log("FETCH_BLOG_POST.catch")
reject(error)
})
});
}

"Maximum call stack size exceeded" by passing the data to the Vuex-state

I am fetching the data from a MongoDB through sending GET requests to my API. Then I loop through the response.data and in each response.data through its properties to push the data which I need to nextArray. And this nextArray should be passed to the schedulingQuality-state in the Vuex. That's how it looks like:
methods: {
...mapActions(
['setSchedulingQuality']
),
get_data() {
const nextArray = [];
for(let i in this.SelectedtValues) {
axios.get('http://127.0.0.1:5000/getexp/'+this.SelectedtValues[i])
.then(res => {
for(let n in res.data) {
nextArray.push(res.data[n].output)
}
}
)}
console.log(nextArray);
},
computed: {
...mapGetters(
['schedulingQuality','selectedValues']
),
SelectedtValues() {
return this.$store.getters.selectedValues;
} ,
schedulingQuality() {
return this.schedulingQuality;
}
}
When I'm printing out the nextArray then it seems to be ok. I'm getting a [] on the console and after I click on it the correct content appears with a small i icon which tells: "Value below was evaluated just now". However I am not able to print out the items of this Array separately, each of them has a value of undefined, when I try that.
But my main problem is that it throws an Maximum call stack size exceeded error, when I'm trying to pass it to my Vuex-state in the code above befor printing out, like:
this.setSchedulingQuality(nextArray)
Here is my Vuex-code:
import Vuex from "vuex";
import axios from "axios";
const createStore = () => {
return new Vuex.Store({
state: {
schedulingQuality: [],
},
mutations: {
SchedulingQuality(state, payload) {
state.schedulingQuality = payload;
}
},
actions: {
setSchedulingQuality({commit}, payload){
commit('SchedulingQuality',payload)
}
},
getters: {
schedulingQuality(state) {
return state.schedulingQuality;
}
}
});
};
export default createStore;
My questions are:
Why it is not possible to print out the Array items separately?
Why I'am getting this error
And how can I fix it?
Thank you for your time.
axios call is asynchronous. At the time you call console.log(nextArray), axios function is not finished yet. That's why you got empty array.
You call multiple api asynchronously, I suggest you check out Promise.all
get_data() {
const nextArray = [];
Promise.all(this.SelectedtValues.map(value => {
return axios.get('http://127.0.0.1:5000/getexp/' + value)
})).then(results => {
results.map(res => {
for(let n in res.data) {
nextArray.push(res.data[n].output)
}
})
console.log(nextArray);
}).catch(err => {
console.error(err)
})
}