How to outsource asyncData to Vuex Store? - vue.js

I'm currently loading some data from firebase I wan't to be server side rendered so it can be indexed for SEO in asyncData on a page.
asyncData() {
return firebase.firestore().collection('Programms').get().then((querySnapshot) => {
const programms = [];
querySnapshot.forEach((doc) => {
const programm = doc.data();
programm.id = doc.id;
programms.push(programm)
})
return { programms: programms};
})
However I would like to convert this to my vuex store.
I know I could do this:
const actions = {
async nuxtServerInit({ commit }) {
firebase.firestore().collection('Programms').onSnapshot((querySnapshot) => {
const programms = [];
querySnapshot.forEach((doc) => {
const programm = doc.data();
programm.id = doc.id;
programms.push(programm)
})
console.log('loaded Programms', programms)
commit('setProgramms', programms);
})
},
}
But this way the data will be loaded for every route in my app. I wan't to load this data only in some pages where I also display it, so I don't load it unnecessary.
How could I do this in Vuex?

As #aldarund says, the fetch method is precisely what you want.
fetch ({ store, params }) {
return firebase.firestore().collection('Programms').get().then((querySnapshot) => {
const programms = [];
querySnapshot.forEach((doc) => {
const programm = doc.data();
programm.id = doc.id;
programms.push(programm)
})
.then(() => {
store.commit('setPrograms', programms)
})
}
See the docs here.

Related

React Native undefined is not an object while fetching data

I want to print a document that uses data that I need to fetch first but it always gets 'undefined is not an object (evaluating 'items.username')' error since the items are still in the fetch state while the HTML variable is created
here's an example of my code
const [items, setItems] = React.useState();
const [loading, setLoading] = React.useState(true)
const getData = async () => {
const response = await axiosInstance.get(`/userData/get`)
if (response?.data?.success) {
const result = response.data?.result[0] || [];
setItems(result);
}
}
React.useEffect(() => {
(async () => {
setLoading(true);
try {
await getData();
} catch (err) {
Alert.alert("", err?.response?.data?.message || err?.message);
}
setLoading(false);
})();
}, []);
const userHTML = `<h1>${items.username}</h1>`
const printHTML = async () => {
await Print.printAsync({
userHTML,
});
};
is there a way to delay the userHTML creation so it will be generated after the fetching is done or maybe there is a best practice to do this kind of thing?
note: the print function will be on the same page as where the userData is being fetched since the data always changed so it will not be possible to fetch data and store it first then move to the page with the print function
You can set the useHTML like this:
const userHTML = `<h1>${!!items ? items.username : ''}</h1>`

How to use redux on a global functions

Iam currently working with a react-native project and wanted to use redux now what i want is that a global function that handles all firebase fetch data here is my globla function
connectFunctions.js
export const pullDataFromFirebaseSubCollection = async (collectionName, docId, subCollection, reducerName,) => {
const q = query(collection(db, collectionName,docId,subCollection));
const querySnapshot = await getDocs(q);
const documents = querySnapshot.docs.map((doc) => ({ key_id: doc.id, ...doc.data() }));
var redData = {
reducerName:reducerName,
data:documents
}
store.dispatch(middlewareDispatch(redData))//tried it inside the function does not work
return documents;
}
so on my App.js i imported then connectFunction.js and use pullDataFromFirebaseSubCollection
useEffect(()=>{
let isMounted = true; // note mutable flag
onAuthStateChanged(auth, (user) => {
if (user) {
console.log("user appjs", user);
dispatch(updateLoginStatus(true));
pullDataFromFirebaseSubCollection("Students","1","playlist","playlist").then((data)=>{
}).catch((err)=>{
console.log("logged error", err);
})
} else {
dispatch(updateLoginStatus(false))
}
_handleFinishLoading()
})
return () => { isMounted = false }
},[])
so on my library.js
i called store.getState().reducer.playlist the result is empty

React Native fecth data from firestore then dispatch not working-Dispatch empty array

I am trying to developp my 1st React Native app but I am bloqued with store/fetching data from firestore.
The problem is that is dispatch before fetching all data from firestore so my filteredProfiles array is empty and my flat list in my screen is so empty too.
what should I modify? If someone could help me, i will appreciate..Thanks!!
here is my code in my screen:
ProfilesListScreen.js
const ProfilesListScreen = props => {
const connectedUser = useSelector(state => state.profiles.user);
const filteredProfiles = useSelector(state => state.profiles.filteredProfiles)
const dispatch = useDispatch();
useEffect(() => {
dispatch(fetchProfiles());
}, [dispatch]);
My profilesAction.js in my store :
export const fetchProfiles= () => {
const loadedProfiles = [ ];
return async dispatch => {
await firebase.firestore().collection('users')
.get()
.then((profileSnapShot) => {
profileSnapShot.forEach((doc) => {
const firstname= doc.get("firstname");
const birth = doc.get("birth");
const age = getAge(birth.seconds);
const sex = doc.get("sex");
const newProfile= new profile(doc.id, firstname,age, "https://www.google.fr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png");
loadedProfiles.push(newProfile);
});
})
dispatch({ type: SET_PROFILESLIST, profilesList: loadedProfiles } ) ;
};
and my reducer profiles.js
case SET_PROFILESLIST:
const newProfilesList = action.profilesList;
return {
filteredProfiles : newProfilesList,
};
Have a try by updating the code for fetchProfiles as below this might help you with your issue.
export const fetchProfiles= () => {
const loadedProfiles = [];
return async dispatch => {
const profileSnapShot = await firebase.firestore().collection('users').get()
profileSnapShot.forEach((doc) => {
const firstname= doc.get("firstname");
const birth = doc.get("birth");
const age = getAge(birth.seconds);
const sex = doc.get("sex");
const newProfile= new profile(doc.id, firstname,age, "https://www.google.fr/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png");
loadedProfiles.push(newProfile);
});
dispatch({ type: SET_PROFILESLIST, profilesList: loadedProfiles });
}
};

React Hook: Pass one value from custom react hook to another react custom hook?

I am trying to figure out how custom hooks are working. I want to get the person ID from one custom hook and pass the ID to a custom hook to get the user details. Is this working?
The user detail hook is always executed first and because of this it is not working.
App.js
const username = props.navigation.getParam('username');
const id = usePersonId('username');
const userInfo = useUserInfo(id);
usePersonId
export default (username) => {
const [personId, setPersonId] = useState(0);
useEffect(async () => {
let token = await new keys().getToken();
let x = await new userService().getPersonId(token, username);
setPersonId(x.user_id);
return () => {
console.log("cleaned up");
};
}, [])
return personId;
}
useUserInfo
export default (id) => {
const [userInfo, setUserInfo] = useState('');
useEffect(async () => {
let token = await new keys().getToken();
let x = await new userDetails().getUserInfo(token, id);
const info = {
"picture": pictureUrl,
};
setUserInfo(info);
return () => {
console.log("cleaned up");
};
}, [])
return userInfo;
Thanks,
Jan

Reusing async function in react native

I am building a page to fetch data from API when loaded, but encounter waring an effect function must not return anything besides a function which is used for clean-up when trying to reuse the function for fetching data
const dispatch = useDispatch();
useEffect(() => {
// this way does not work as I expected, my page does not show data I fetched
const getData = async () => {
const result = await dispatch(actions.getList());
setState(result);
};
getData();
},[isFirstLoaded]);
But I get the warning when trying below
const dispatch = useDispatch();
const getData = async () => {
const result = await dispatch(actions.getList());
setState(result);
};
useEffect(async() => {
// this way gives me the data but with a warning
await getData();
},[isFirstLoaded]);
How should I reuse the getData function? I did not update the state if I am not using the async and await here. When I use async and await here, I get the warning. Thanks.
overall, you are heading in the right direction. For fetching data, you'd wanna use use Effect and pass [] as a second argument to make sure it fires only on initial mount.
I believe you could benefit from decoupling fetching function and making it more generic, as such:
const fetchJson = async (url) => {
const response = await fetch(url);
return response.json();
};
const Fetch = () => {
const [data, setData] = useState(null);
useEffect(() => {
fetchJson("https://api.coindesk.com/v1/bpi/currentprice.json")
.then(({ disclaimer }) => setData(disclaimer));
}, []);
return <Text>{data}</Text>;
};