Error while rendering an array from firestore to react native - reactjs

i have an array that i am trying to read and store in a state however, with the code below, here is the error i get: "function collectionReferenace.doc() requires its first argument to be of type non-empty string, but it was undefined" any idea why this is happening and what is the solution?
componentDidMount(){
dbh.collection('Groups').doc(this.props.route.params.groupName)
.collection('Enrolled').doc('ids').get()
.then(querySnapshot => {
querySnapshot(doc => {
this.setState({
playerIDs: doc.data().players
})
})
})
console.log(this.state.playerIDs)
}
the this.props.route.params.groupName is passed from the navigation of the previous screen. When I set a constant in the render function to it and call that variable it works fine.
render() {
const groupName = this.props.route.params.groupTitle
return
<Text>{groupName}</Text>
for your reference, here is how i am getting that route.param
<GroupComponent onPress = {
() => this.props.navigation.navigate
('Attendance', {groupTitle: group.GroupName, groupID: group.id})
} />

Based on your code, you should be acccessing dbh.collection('Groups').doc(this.props.route.params.groupTitle) not groupName. The object you pass through params has keys groupTitle and and groupID, not groupName.

Related

Use the value resolved by async function in material UI Table Row / Table Cell

I have a table that is calling and passing some data through the cells prop of a MUI TableRow.
Some of the data that I need is exposed and consumable immediately from what is being passed in the cells prop array; in order to find other data that I would like (the name of a show) I need to make a call to an async function using that data (I need to make a call to get a show name from within a table using just the exposed showId).
Heres what I mean
<TableBody>
{pushNotifications?.items.map(
(pushNotification: IPushNotificationDTO) => {
const {
id,
showId,
notification: { title },
audienceType,
createdAt,
sendAt,
} = pushNotification;
return (
<TableRowComponent
cells={[
//this is the async call
getShowName(showId),
title,
formatPushNotificationAudience(audienceType),
new Date(createdAt),
new Date(sendAt),
]}
isSelected={selectedRow === pushNotification.id}
onSelect={setSelectedRow}
redirectTo={APP_DASHBOARD_PUSH_NOTIFICATIONS_PAST_PATH(
pushNotification.id
)}
key={pushNotification.id}
id={id}
/>
);
}
)}
</TableBody>
And the function itself
const getShowName = async (showId?: string) => {
const response = await getShow(showId);
//logs expected data, a string name, or undefined
console.log("logging response in getShowName ",response.name)
return response.name
};
The code compiles, but I get the error Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
How can I access the data I need using an async call to a function that accepts an id I only have within the table?
Thanks!

ReactJS: querySelectorAll .map function not working as expected with State

I am trying to push my querySelectorAll .map function to a React State Array but its not working as expected.
const [affectedServices, setAffectedServices] = useState([]);
function affectedTags() {
Array.from(document.querySelectorAll(".active-tag")).map((tag) => {
console.log(tag.innerHTML);
setAffectedServices([tag.innerHTML]);
});
}
console.log(tag.innerHTML) will display all querySelected tags e.g.
Active tag 1
Active tag 2
Active tag 3
But when viewing the affectedServices state from React Dev tools, it only has one array which contains Active tag 3
Any ideas of what im doing wrong?
TIA
Try like this.
I think I will works for you.
const [affectedServices, setAffectedServices] = useState([]);
function affectedTags() {
setAffectedServices(Array.from(document.querySelectorAll(".active-tag")).map((tag) => {return tag.innerHTML})));
}
you need to push the value in the array at every loop, and not just replacing the previous value by a new, can you try this ?
useEffect(() => {
console.log("affectedServices ", affectedServices);
}, [affectedServices]);
function affectedTags() {
let result = [];
Array.from(document.querySelectorAll(".active-tag")).forEach((el) => {
result.push(el);
});
setAffectedServices(result);
}

Firebase Error: Objects are not valid as a React child (found: object with keys {seconds, nanoseconds})

First I query for my data from firebase:
useEffect(() => {
if (user) {
async function fetchData() {
const request = await db
.collection("users")
.doc(user)
.collection("notifications")
.onSnapshot((snapshot) =>
setNotifications(
snapshot.docs.map((doc) => ({ ...doc.data(), id: doc.id }))
)
);
}
fetchData();
} else {
setNotifications([]);
}
}, [user]);
The query returns this:
Now, when I try to render the data:
<div className="notifications">
{notifications.map((notification) => (
<NotificationContainer
notificationType={notification.notificationType}
notificationFrom={notification.notificationFrom}
timestamp={notification.timestamp}
linkId={notification.linkId}
/>
))}
When I try to render the data on the page, I get the following error:
Error: Objects are not valid as a React child (found: object with keys {seconds, nanoseconds}). If you meant to render a collection of children, use an array instead.
Any idea what I am doing wrong? I think there may be something wrong in the day I am reading the data from my notifications array
Short answer is somewhere in your code, you're trying to render object.
Something like this will give you that error "Object are not valid React Child"
const obj = { a: 1 }
const SomeComponent = () => {
return (
<div>{obj}</div>
)
}
In your case, I assume "notification" is an object that look like this, firebase return timestamp in object format
notification: {
timestamp: {
seconds: 1700000000,
nanoseconds: 1700000000000,
}
}
Thus in must have somewhere that try to render this object
return (
...
<div>{timestamp}</div>
...
)
If you find this and change to
return (
...
<div>{timestamp.seconds}</div>
...
)
Should make the error disappear.
So I was using the timestamp firebase field. And when I tried to render it, the nasty error I was talking about pops up.
The timestamp is not a string and most likely an object.

Warning for render method that should be a pure function of props and state

I have a component that I render when there is an alert that's pulled from the state. Currently the alert dispatches and displays but i'm getting the following error and i'm not sure how I would rework this component to comply.
Error:
Warning: Render methods should be a pure function of props and state; triggering nested component updates from render is not allowed. If necessary, trigger nested updates in componentDidUpdate.
const Alerts = ({ alerts }) =>
alerts !== null &&
alerts.length > 0 &&
alerts.map((alert) =>
notification[`${alert.type}`]({
key: `${alert.id}`,
message: `${alert.title}`,
description: `${alert.message}`,
})
);
Indeed the render function should be pure and without side-effects. Remember, the entire function body of a functional component is the render function. Use an useEffect hook to issue side-effects.
Also, instead of using array::map, use array::forEach as that is the intended array function to issue side-effect on an array.
Remember to explicitly return null from the function to indicate to react there is nothing to render.
const Alerts = ({ alerts }) => {
useEffect(() => {
if (alerts) {
alerts.forEach(alert => {
notification[alert.type]({
key: alert.id,
message: alert.title,
description: alert.message,
})
})
}
}, [alerts]);
return null;
};
I think you are not able to return an array of ReactElements that way, try this:
const Alerts = ({ alerts }) => {
if(alerts !== null &&
alerts.length > 0) {
return
(<>
{alerts.map(({type, id, title, message}) =>
notification[type]({
key: `${id}`,
message: `${title}`,
description: `${message}`,
})}
</>)} else { return null }
});

How to write a unit test to cover custom PropTypes in reactjs?

I have a reactjs component with a custom properties, that actually represents just a list of allowed extensions.
For example, my component can receive as a prop something like this:
<CustomComponent allowedTypes={['.pdf', '.txt']} />
and the prop types are defined like this
CustomComponent.propTypes = {
allowedTypes: PropTypes.arrayOf(
(propValue, key, componentName, location, propFullName) => {
if (!new RegExp(/^\.[^.]+$/).test(propValue[key])) {
return new Error(
`Invalid prop ${propFullName} for component ${componentName}.`
)
}
}
)
I need to full cover the component with unit test, so also the code in the prop type definition must be covered.
I tried something similar, but it doesn't work
beforeEach(() => {
console.error = jest.fn()
});
it('should check wrong allowed types', () => {
const wrongAllowedTypes = false
try {
const component = new CustomComponent(Object.assign(defaultProps, { allowedTypes: wrongAllowedTypes } ))
} catch (error) {
expect(console.error).toBeCalled()
}
})
Any ideas, thanks in advance
I suggest pulling out the fat arrow function and giving it a name. Then you can call it directly from a test.

Resources