Why split property is undefined here? I fetched the products from my product api through axios, I received json data that have some properties(name,description,...)
const [product, setProduct] = useState({});
let substrings=[];
useEffect(() => {
const getProduct = async () => {
try {
const res = await axios.get(`/products/${props.match.params.id}`);
setProduct(res.data);
} catch (error) {
console.error(error);
}
};
getProduct();
//eslint-disable-next-line
}, []);
const substrings = product.description.split(".");
This is the json that we get from products/id
{"_id":"1","name":"Mangoes","image":"https://drive.google.com/thumbnail?id=1Iq2F4fYxDi7HdX-IJcRuON-CbNuK-pxd","description":"This sweet and fresh mangoes make your day sweet","category":"Fruits","keywords":"fruits","price":120,"countInStock":0,"content":""}
whereas it works fine here
const [product, setProduct] = useState({});
const [desc,setDesc]=useState("");
useEffect(() => {
const getProduct = async () => {
try {
const res = await axios.get(`/products/${props.match.params.id}`);
setProduct(res.data);
setDesc(res.data.description);
} catch (error) {
console.error(error);
}
};
getProduct();
//eslint-disable-next-line
}, []);
const substrings = desc.split(".");
Can anyone tell us why is it so?
I think before the load product, the value of your product is null or {},
so when you use product.description the value will be undefined.
You can use:
const substrings = (product?.description || '').split(".");
I think the problem here is the way you declared the product using useState. For the second part you declare the description directly so when you split it, it might be an empty string or whatever you declared it, but not undefined.
But for the first part, you declare just the product variable, without the description property. So before fetching, when you try to split product.description, it is undefined and becomes a value just after fetching.
In order to fix it you might declared the product like this:
const [product, setProduct] = useState({ description: "" }) or just simply use ? operator like this: const substrings = product.description?.split(".");
Also there might be a problem because you first declare substrings as an empty array and then you declare it again as a const.
Related
Im trying to just use a empty array in a react/ts project like this.
const [companyChatrooms, setCompanyChatrooms]: any = useState([]);
I then use a useEffect to get it done when rendering component.
async function fetchMyChatRooms() {
const userCollection = await firestore.collection('user_in_chat')
const snapshot = await userCollection.where('user_id', '==', myIdNumber).where('chatroom_id', '==', companyChatrooms).get();
snapshot.forEach(doc => {
const roomID = doc.data().chatroom_id
setMyChatrooms([...myChatrooms, roomID])
});
}
fetchMyChatRooms()
}, [companyChatrooms, myIdNumber])
console.log(myChatrooms)```
However, my console.log shows 2 arrays with each value instead of 1 array holding both values.
How can i make sure both values are stored in same array?
[1]: https://i.stack.imgur.com/q0WPD.png <-- Check how the output looks.
I assume you have an array snapshot with more than 1 element and any iteration you are updating the state. This caused multiple re-render
I suggest you to update state after iterate entire array. Example:
const rooms = []
snapshot.forEach(doc => {
const roomID = doc.data().chatroom_id;
rooms.push(roomID);
});
setMyChatrooms(rooms)
you should set all of them in one time.
async function fetchMyChatRooms() {
const userCollection = await firestore.collection('user_in_chat')
const snapshot = await userCollection.where('user_id', '==', myIdNumber).where('chatroom_id', '==', companyChatrooms).get();
// here is the changing
const roomIDs = snapshot.map(doc => doc.data().chatroom_id);
setMyChatrooms(roomIDs )
//
fetchMyChatRooms()
}, [companyChatrooms, myIdNumber])
console.log(myChatrooms)
I was following this tutorial https://www.sitepoint.com/reddit-clone-react-firebase/.
Earlier it was really simple just call onSnapshot after the document is fetched, but here it is a separate function, and now here comes the issue, when I try to call that onSnapshot by passing document, but it always says,no matter what type of data I tried to pass it as the first param, it always says, it is not type of 'bc' which it expects.
FirebaseError: Expected type 'bc', but it was: a custom he object
useEffect(async () => {
const postsCollection = collection(db, "posts");
const orderedCollection = query(
postsCollection,
orderBy("createdAt", "desc")
);
try {
onSnapshot(
orderedCollection, // here I think the problem is!
(querySnapshot) => {
console.log("yahaan se problem hai");
console.log(querySnapshot);
const _posts = [];
querySnapshot.forEach((doc) => {
console.log(doc);
_posts.push({
id: doc.id,
...doc.data(),
});
});
console.log(_posts);
// setPosts(_posts);
},
(error) => {
console.log("error occured: ", error);
},
() => {
console.log("completed");
}
);
} catch (e) {
console.log("ye kya drama hai:", e);
} finally {
console.log("finally");
}
}, []);
Okey, so I had the same problem and I found a solution after struggling with the newest version of firebase for a while.
I don't know if you're using a class component or a functional one, in this example i'm using a funcional component but I assume it'll work the same if you replace the react hooks.
import { getFirestore, collection } from 'firebase/firestore'
const db = getFirestore();
const colRef = collection(db, "team")
const [results, setResults] = useState([]);
useEffect(() => {
let isMounted = true;
onSnapshot(colRef, (snapshot) => {
if (isMounted) {
const results= snapshot.docs.map((doc) => {return {...doc.data(), id: doc.id}});
setResults(results)
}
});
return () => { isMounted = false };
}, []);
This way your component'll listen to updates everytime the data changes, after that you can personalize it using querys but i wanted to show you a simple example so it's easy to understand.
I had the same problem, unfortunately, the above didn't help me. in my case I was actually importing form functions and types from '#firebase/firestore' and others from 'firebase/firestore'... this was done by autoImport. the moment I made all of them get the types and functions from the same place it worked instantly
These kind of errors occur usually when the functions aren't used the way they're supposed to. I can't really tell where the problem comes from in your code but you may try the getDocs method instead and a state variable to store your values
try this code.
const [Results, setResults] = useState([]);
useEffect(() => {
const FetchedPosts = async () => {
const querySnapshot = await getDocs(
collection(db, 'posts'),
orderBy("createdAt", "desc")
);
querySnapshot.forEach((doc) => {
setResults((prevState) => [...prevState, doc.data()]);
});
};
FetchedPosts();
}, []);
I have been trying to push or store a FireStore array in one of my own arrays. I have tried a few versions of code, the first being this:
var data = [];
db.collection('Rooms')
.doc(code)
.get()
.then((docs) => data.push(docs.data()));
However, when I log the data variable, it comes out as an empty array. The second method I have tried is this:
var [data, setData] = useState([]);
db.collection("Rooms")
.doc(code)
.get()
.then((docs) => setData(docs.data()));
However this method seems to setData infinitely, so it is reading into my API infinitely, which I would like to avoid. The last method I tried was this:
var data = db.collection("Rooms").doc(code).get();
console.log(data);
But this just returns
Promise {
"_U": 0,
"_V": 0,
"_W": null,
"_X": null,
}
Could anyone help me with this, ideally I'd like to store the data of an array called "MovieArray" inside the document, but I can't even access the document, so even if you can just help me store the data of the whole document, it would be very helpful.
If you are using react, I would suggest using the hook. You also, don't really need to push objects to an array like that.
Here is an example of how to get some data and store the collection of data.
const Forum = () => {
const [posts, setPosts] = useState(null);
const collectIdsAndDocs = (doc) => {
return { id: doc.id, ...doc.data() };
};
useEffect(() => {
const getPost = async () => {
const snapshot = await firestore.collection('Posts').get();
const myPosts = snapshot.docs.map(collectIdsAndDocs);
console.log(myPosts);
setPosts({ myPosts });
};
const createPost = async (post) => {
const docRef = await firestore.collection('Posts').add(post);
const doc = await docRef.get();
console.log(doc);
};
createPost({ Title: 'My First Post', Content: 'My content' });
getPost();
}, []);
return (
// return some JSX
);
};
Why does this work?
When you get a collection, Firebase returns a snapshot of the collection.
This snapshot has a list of docs or an array if you will.
We then want to map over those docs constructing a new object that contains just the document data and the ID of individual doc. This is what the myPosts variable is.
Using the react state hook, you can set that object to the current state of Posts, in your case this would be rooms.
When you add something to the database, Firestore will return a reference to the newly added item. You can then call get() to get the document back if you need it.
Try changing to (see comment before this)
const [data, setData] = useState({});
I'm trying to fetch a value from my firebase DB and I'm using the following code:
export const getCode = async key => {
let ref = await database.ref ('games/' + key).once('value');
console.log(ref);
console.log(ref.code);
return ref;
};
The results I get from each console.log are these:
the ref returns
Object {
"code": 665195,
"users": Object {
"-MA5m0PrOWUuz-KdcmRx": Object {
"username": "לעג",
},
},
}
but ref.code returns undefined
screenshot
I've spent hours on my code and stackoverflow and couldn't find an answer. Hopefully you could.
you didn't use ref.val() to get values.
try
export const getCode = async key => {
let ref = await database.ref('games/' + key).once('value');
const data = ref.val();
console.log(data);
console.log(data.code);
return data.code;
};
If ref gets logged as the following:
Object {
"code": 665195,
"users": Object {
"-MA5m0PrOWUuz-KdcmRx": Object {
"username": "לעג",
},
},
}
I suspect that it could be that you're getting a json string as a response, unless your development environment quotes keys by default.
Maybe try let ref = JSON.parse(await database.ref ('games/' + key).once('value'));
Shouldn't the ref variable be returned? You haven't declared anything named code hence why it's undefined.
export const getCode = async key => {
let ref = await database.ref ('games/' + key).once('value');
return ref.code;
};
You could also do like the cool kids and make this single line if you are gonna use it as it is.
export const getCode = async key => await database.ref ('games/' + key).once('value').code
I am trying to extract value in React hooks but in meantime when I console customer I got this error TypeError: Cannot read property 'firstName' of null I don't know what issue have in my code . I am new to React Hook could someone please help me how to solve this problem .
Thanks
When I console Customer , I am getting this result
Result View
When I console customer.firstName
It give me error
Code
const [customer, setCustomer] = useState(null);
async function fetchMyAPI() {
let response = await fetch(
`/api/requirements/find?customerId=${item.customerId}`
);
response = await response.json();
console.log(response);
setCustomer(response);
}
useEffect(async () => {
fetchMyAPI();
}, []);
In return function
{console.log(customer.firstName)}
The error makes sense, you are using Object notation to reach the value belonging to something that is not an object.
Just set your initial-state as an empty object to resolve your console error:
const [customer, setCustomer] = useState({});
Overall code:
const Customer = () => {
const [customer, setCustomer] = useState(null);
async function fetchMyAPI() {
let response = await fetch(
`/api/requirements/find?customerId=${item.customerId}`
);
let data = await response.json();
console.log(data);
setCustomer(data);
}
useEffect(async () => {
fetchMyAPI();
}, []);
return(
<div>
<h4>{customer.firstName}</h4>
<h4>{customer.lastName}</h4>
</div>
)
}
You can set the initial state as blank object like below...
const [customer, setCustomer] = useState({});
OR
You may set the default structure of object like below...
const [customer, setCustomer] = useState({firstName: '', lastName: ''});