use Effect not working to bring up my product, using axios use params, - mongodb

This code is not working for me i am trying to pull data from my mongodb
const ProductScreen = ({ match }) => {
const [product, setProduct] = useState({});
const { id } = useParams();
useEffect(() => {
const fetchProduct = async () => {
const { data } = await axios.get(
`/api/product/${encodeURIComponent(id)}`
);
setProduct(data);
};
fetchProduct();
}, []);
};
pull data from server of mongo db

It is possible when the component first mounts, id is null and useParams() doesn't get it till the second render. So add an if statement in your useEffect to make sure the id is present. Also add id to the dependency array, so if the id changes, you will refetch the data for it. Otherwise, with an empty dependency array, the useEffect will only run on first mount.
const ProductScreen = ({ match }) => {
const [product, setProduct] = useState({});
const { id } = useParams();
useEffect(() => {
const fetchProduct = async () => {
const { data } = await axios.get(
`/api/product/${encodeURIComponent(id)}`
);
setProduct(data);
};
if (id) {
fetchProduct();
}
}, [id]);
};

Related

Propagate live updates return promise object instead of value

Working on beginner steps toward vue 3 and firestore migration. Stuck on simple.
import { getUsersCount } from "/src/firebase";
setup() {
const usersCount = getUsersCount();
return {
usersCount,
};
},
Why it returns Promise Object, I cant find in manuals.
export const getUsersCount = async () => {
// const querySnap = await getDocs(query(collection(db, "users")));
const q = query(collection(db, "users"));
const unsub = onSnapshot(q, (querySnapshot) => {
console.log("usersCount33: ", querySnapshot.size);
//unsub();
return querySnapshot.size;
});
}
Nad the last part with template,
<template>
<p>Users Count: {{ usersCount }}</p>
</template>
If you return the value inside a callback, you can not use async await syntax. You should do this:
export const getUsersCount = () => {
return new Promise((resolve, reject) => {
const q = query(collection(db, "users"));
const unsub = onSnapshot(q, (querySnapshot) => {
return resolve(querySnapshot.size)
});
})
}
// You still need to wait getUsersCount when using it
const usersCount = await getUsersCount();

Can't fetch data with react-query

On my client-side(React js), I want to fetch data from the backend. But it's not working. The output of data is undefiend. Code Snippets
const url = `http://localhost:5000/items/${id}`;
const { data } = useQuery("data", () => axios(url));
console.log("data", data);
In the backend, I am using Express js and MongoDB as databases.
Try creating a function for fetching, for example:
const fetchData = async (id) => {
try {
const URL = `http://localhost:5000/items/${id}`;
const response = await axios.get(URL);
return response;
} catch(error) {
console.log(error);
}
}
Then:
const { data } = useQuery("data", () => fetchData(id));
You have to provide the id to fetchData

Nexjs + SWR: API resolved without sending a response for /api/projects/<slug>, this may result in stalled requests

Since on first render I was not able to get the router.query I am passing the params from getServerSideProps as follows:
export async function getServerSideProps(context) {
return {
props: { params: context.params },
};
}
Then in the function am trying to do the API call but am getting the API stalled error
API resolved without sending a response for
/api/projects/nichole_robel23, this may result in stalled requests.
This is my code:
export default function Project({ params }) {
const { slug } = params;
let [projectData, setProjectData] = useState([]);
let [loading, setLoading] = useState(true);
const { data } = useSWR('http://localhost:3000/api/projects/' + slug);
useEffect(() => {
if (data) {
setProjectData(data.data.project);
setLoading(false);
}
}, [data]);
......
I have global SWRCofig as follows
<SWRConfig value={{ fetcher: (url) => axios(url).then(r => r.data) }}>
<Layout>
<Component {...pageProps} />
</Layout>
</SWRConfig>
Any way to solve the problem?
You are missing your fetcher–the function that accepts the key of SWR and returns the data, so the API is not being called.
You are also not returning a response correctly from the API–this is most likely a case of not waiting for a promise/async to be fulfilled correctly.
CLIENT
const fetcher = (...args) => fetch(...args).then((res) => res.json());
export default function Home({ params }) {
const { slug } = params;
const [projectData, setProjectData] = useState([]);
const [loading, setLoading] = useState(true);
const { data } = useSWR(`http://localhost:3000/api/projects/${slug}`, fetcher);
useEffect(() => {
if (data) {
setProjectData(data);
setLoading(false);
}
}, [data]);
API
const getData = () => {
return new Promise((resolve, reject) => {
// simulate delay
setTimeout(() => {
return resolve([{ name: 'luke' }, { name: 'darth' }]);
}, 2000);
});
}
export default async (req, res) => {
// below will result in: API resolved without sending a response for /api/projects/vader, this may result in stalled requests
// getData()
// .then((data) => {
// res.status(200).json(data);
// });
// better
const data = await getData();
res.status(200).json(data);
}

Why my firebase update function is not always working?

Im trying to figuring out why my firebase funtion for cheat is always creating but when like open the chat where it call create function immediately send a message the message will not be saved, because my function is not ready so how can I sole this?.
Heres my function .
export const onConversationCreated = functions.firestore.
document("Conversations/{conversationID}").onCreate((snapshot, context) => {
const data = snapshot.data();
const conversationID = context.params.conversationID;
if (data) {
const members = data.members;
for (let index = 0; index < members.length; index++) {
const uid = members[index];
const remainingUserIDs = members.filter((u: string) => u !== uid);
remainingUserIDs.forEach((m: string) => {
return admin.firestore().
collection("profile").doc(m).get().then((_doc) => {
const userData = _doc.data();
if (userData) {
return admin.firestore().collection("profile")
.doc(uid).collection("Conversations").doc(m).create({
"conversationID": conversationID,
"url": userData.url,
"name": userData.username,
"unseenCount": 0,
});
}
return null;
}).catch(() => {
return null;
});
});
}
}
return null;
});
export const onConversationUpdated = functions.firestore
.document("Conversations/{conversationID}").onUpdate((change, context) => {
const data = change?.after.data();
if (data) {
const members = data.members;
const lastMessage = data.messages[data.messages.length - 1];
for (let index = 0; index < members.length; index++) {
const uid = members[index];
const remainingUserIDs = members.filter((u: string) => u !== uid);
remainingUserIDs.forEach((u: string) => {
return admin.firestore().collection("meinprofilsettings")
.doc(uid).collection("Conversation").doc(u).update({
"lastMessage": lastMessage.message,
"timestamp": lastMessage.timestamp,
"type": lastMessage.type,
"lastmessageuid": lastMessage.senderID,
"unseenCount": admin.firestore.FieldValue.increment(1),
});
});
}
}
return null;
});
So again creating is correct working. its just need some time . And when I immediately when calling create function write a message and send it this message will not be saved until the create function is finished then I have to send again the message
enter image description here
The reason for your bug is that you don't await the execution of your async task correctly. Unfortunately the forEach doesn't support async so we need to revrite your code to something like this:
export const onConversationCreated = functions.firestore
.document("Conversations/{conversationID}")
.onCreate((snapshot, context) => {
const data = snapshot.data();
const promises: Promise<any>[] = [];
const conversationID = context.params.conversationID;
if (data) {
const members = data.members;
for (let index = 0; index < members.length; index++) {
const uid = members[index];
const remainingUserIDs = members.filter((u: string) => u !== uid);
remainingUserIDs.forEach((m: string) => {
promises.push(
admin
.firestore()
.collection("profile")
.doc(m)
.get()
.then((_doc) => {
const userData = _doc.data();
if (userData) {
return admin
.firestore()
.collection("profile")
.doc(uid)
.collection("Conversations")
.doc(m)
.create({
conversationID: conversationID,
url: userData.url,
name: userData.username,
unseenCount: 0,
});
}
return null;
})
);
});
}
}
return Promise.all(promises);
});
export const onConversationUpdated = functions.firestore
.document("Conversations/{conversationID}")
.onUpdate((change, context) => {
const data = change?.after.data();
const promises: Promise<any>[] = [];
if (data) {
const members = data.members;
const lastMessage = data.messages[data.messages.length - 1];
for (let index = 0; index < members.length; index++) {
const uid = members[index];
const remainingUserIDs = members.filter((u: string) => u !== uid);
remainingUserIDs.forEach((u: string) => {
promises.push(
admin
.firestore()
.collection("meinprofilsettings")
.doc(uid)
.collection("Conversation")
.doc(u)
.update({
lastMessage: lastMessage.message,
timestamp: lastMessage.timestamp,
type: lastMessage.type,
lastmessageuid: lastMessage.senderID,
unseenCount: admin.firestore.FieldValue.increment(1),
})
);
});
}
}
return Promise.all(promises);
});
We use Promise.all() to even run all your async tasks in parallel to finish the function faster and save on execution time.

Best practice for using React hooks and Context API to update global state and fetch/provide data from multiple endpoints

I am new to React hooks/Context API. I have read the React hook/context docs, and I am still having trouble with the following:
My attempts to update global state by multiple consumer components
currently causes frequent overwriting of context state due to
rerendering (e.g., activity or details state is sometimes
null/undefined). This probably is why...
... I am getting 400 (bad request) and/or 500 (server) errors on random refreshes of the page (~30% of the time content loads as
expected, ~70% errors are thrown. I believe this is happening
because we have various context states that are being called
asynchronously).
I am not sure how to implement Axios Cancellation, given that our useEffect hooks are calling dispatch functions (e.g.,
getActivities()) in different files. The examples I've seen
involve fetching data within the component (rather than in context).
I am seeking assistance for #1 specifically. I would love guidance on how to accurately fetch data and store in context as global state, and then provide that context to child components, allowing them to consume/update context state without unnecessary rerendering.
Tried to only provide relevant code snippets below:
ActivityState.js -- should fetch activity data
...
const ActivityState = props => {
const initialState = {
activities: [],
isLoading: false,
isError: false
};
const HEADERS = {
'Content-Type': 'application/json',
'user_id': 1
}
const [state, dispatch] = useReducer(ActivityReducer, initialState);
const userContext = useContext(UserContext);
const getActivities = async () => {
const { loggedIn } = contactContext;
let didCancel = false; // attempts to start implementing axios cancellation
try {
const res = await axios.get(url);
dispatch({ type: GET_ACTIVITIES, payload: res.data.data.activities });
} catch (err) {
if (!didCancel) {
dispatch({ type: 'FETCH_FAILURE' });
}
}
}
const updateActivity = (path, data) => { //update context state
dispatch({ type: UPDATE_ACTIVITY, payload: { path: path, data: data } });
};
const saveActivity = () => { //send new activity data to the backend
const postData = {
actions: [{"293939": []}],
activities: state.activities
};
try {
const res = axios.post(url,{ data: postData }, { headers: HEADERS });
} catch (err) {
console.log(err);
}
}
return (
<ActivityContext.Provider
value={{
activities: state.activities,
data: state.data,
backup_data: state.backup_data,
getActivities,
updateActivity,
saveActivity,
}}
>
{props.children}
</ActivityContext.Provider>
);
};
export default ActivityState;
ActivityReducer.js -- switch statements to be dispatched by ActivityState.js
...
export default (state, action) => {
switch (action.type) {
case GET_ACTIVITIES:
return {
...state,
activities: action.payload,
isLoading: true
};
case FETCH_FAILURE:
return {
...state,
isLoading: false,
isError: true
};
case UPDATE_ACTIVITY:
const { payload: { path }, payload } = action;
const data = state;
if (!data.activities)
return { data };
const index = data.activities.findIndex(e => e.socium_tracking_number == path.id);
if(index === -1)
return { data };
_.set(data, `activities[${index}].${path.field}`, payload.data);
return {
data,
};
...
DetailsState.js -- dispatch functions to fetch details
const DetailsState = props => {
const initialState = {
details: null,
};
const [state, dispatch] = useReducer(DetailsReducer, initialState);
const getDetails = async () => {
try {
const res = await axios.get(url);
dispatch({ type: GET_DETAILS, payload: res.data.data[0].details});
}catch(err) {
console.log(err)
}
};
return (
<DetailsContext.Provider
value={{ details: state.details, getDetails }}
>
{ props.children }
</DetailsContext.Provider>
);
}
export default SchemaState;
DetailsReducer.js -- switch statement
export default (state, action) => {
switch (action.type) {
case GET_DETAILS:
return {
...state,
details: action.payload,
};
default:
return state;
}
};
ActivityTable.js -- component that consumes Activity Info
...
const ActivityTable = ({ activity }) => {
const activityContext = useContext(ActivityContext);
const { activities, filtered, getActivities } = activityContext;
const [order, setOrder] = React.useState('asc');
const [orderBy, setOrderBy] = React.useState(activities.wait_time);
// Get activity data on mount
useEffect(() => {
async function fetchData() {
await getActivities()
}
fetchData();
}, []);
...
CreateActivity.js -- component that consumes Activity and Details data
...
const CreateActivity = props => {
const activityContext = useContext(ActivityContext);
const { activities, filtered, getActivities, addActivity } = activityContext;
const detailsContext = useContext(DetailsContext);
const { details, getDetails } = detailsContext;
// Get activity and details data on mount
useEffect(() => {
async function fetchData() {
await getActivities();
await getSchema();
}
fetchData();
}, []);
...
I really tried to get smarter on these issues before approaching the SO community, so that my question(s) was more defined. But this is what I have. Happy to provide any info that I missed or clarify confusion. Thank you for your time