Im trying to render a component for every item in my Map Object, grouped is typed as
Map<string, Invite[]> | undefined
.map is not an option here, Property 'map' does not exist on type 'Map<string, PactInvite[]>'. Foreach is but this does not return the div or component. How can I render the items in a foreach?
const PendingInvitesView = (props: PendingInvitesProps) => {
const { refetchPactsProfiles, onClickPreviewProfile, grouped } = props
const { t } = useTranslation()
return (
<div className={styles['invite-section']}>
<Accent className={styles['invite-section-title']}>{t('agenda.invites.title')}</Accent>
<Space style={{ width: '100%' }} size="small" direction="vertical">
<>
{grouped?.forEach((element) => {
element.length > 1 ? (
<div>test</div>
) : (
<InviteCard
onClickPreviewProfile={onClickPreviewProfile}
refetchPactsProfiles={refetchPactsProfiles}
invite={element[0] as Invite}
/>
)
})}
</>
</Space>
</div>
)
}
You cannot render items using forEach because return value of this method is undefined.
I propose you convert the Map into array before you do rendering part. Then you should use map method.
Here's one example how to do it.
Related
I have a map component with two childs - GSearchVehicle & MapView - with a positions prop. On the zoomInVehicle function the positions always returns with a empty array, but on the renderCustomCluster function it returns full.
The zoomInVehicle is a function triggered by a custom onPress on GSearchVehicle, it returns the vehicle id that I want to use on the zoomInVehicle. The problem is the positions prop not returning filled.
This is bugging me 'cause positions is filled on all places of the GMap component, but only on that function it returns empty... and it's not a problem about waiting the positions request because it's already filled by the time you call that zoomInVehicle function.
What is the meaning of this behavior? Something with the scope of GSearchVehicle and MapView? I can't see why positions is empty only on that function.
const GMap: React.FC<GMapProps> = ({ positions, selectMarker, selectedMarker }) => {
const mapRef = useRef<MapViewProps | any>(null);
console.log(positions); // [{...}] <--- NOT EMPTY!
const zoomInVehicle = (vehicleId: number): void => {
console.log(vehicleId); // 15486
console.log(positions); // [] <--- EMPTY!
// ...
};
const renderCustomCluster = (cluster: any) => {
console.log(positions) // [{...}] <--- NOT EMPTY!
// ...
}
return (
<>
<GSearchVehicle
placeholder="Digite a placa ou descrição"
onPress={zoomInVehicle}
/>
<MapView
ref={mapRef}
style={{ flex: 1 }}
initialRegion={INITIAL_REGION}
provider={null}
showsCompass={false}
renderCluster={renderCustomCluster}
rotateEnabled={false}
onRegionChangeComplete={getRegionZoom}
>
<UrlTile urlTemplate={TILE_URL} shouldReplaceMapContent />
{/* Draw vehicle marker */}
{ positions.map((position) => (
<Marker
key={position.adhesion.id}
tracksViewChanges={false}
coordinate={position.coordinates}
onPress={() => selectMarker(position)}
>
<GVehicleMarker
key={position.adhesion.id}
position={position}
/>
</Marker>
))}
{/* ... */}
</MapView>
</>
);
};
I found the problem, on the GSearchVehicle component my memoized functions were missing the positions prop on it's dependencies.
const memoizedItems = useMemo(() => renderItem, [vehiclesGroup, positions]);
const memoizedHeader = useMemo(() => renderSectionHeader, [vehiclesGroup, positions]);
I'm getting this "TypeError: Cannot read properties of undefined (reading 'map')"
const Categories = () => {
return (
<Container>
{categories.map((item) =>(
<CategoryItem key={item.id}/>
))}
</Container>
)
}
This means your categories variable is not defined, make sure it does have a value and its a valid array.
categories is undefined so the map function is not available.
if you want to return no category items in this case you can do chained operator to test categories is not null first
https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-7.html
const Categories = () => {
return (
<Container>
{categories?.map((item) =>(
<CategoryItem key={item.id}/>
))}
</Container>
)
}
I am trying to refactor my code and in doing so, I am extracting a single item and putting it into its own component. This MemberItem component has multiple functions state that influence its rendering, however, when I start passing props, the component breaks. I am passing all of the functions, properties and state the the child component needs, but I am still unable to get it to render properly.
// Members.js (Parent Component)
export const Members = () => {
// BELOW ARE THE FUNCTIONS AND STATE THAT INFLUENCE THE CHILD COMPONENT
const [memberName, setMemberName] = useState('')
const [editingMemberName, setEditingMemberName] = useState(
members.map(() => false)
)
// Update member name
const editMemberName = async (_, index) => {
let new_editing_members_state = members.map(() => false)
new_editing_members_state[index] = true
setEditingMemberName(new_editing_members_state)
}
// Cancel editing mode
const cancelEditMemberName = async (_, index) => {
let new_editing_members_state = members.map(() => false)
new_editing_members_state[index] = false
setEditingMemberName(new_editing_members_state)
}
// UPDATE name in database
const updateMemberName = async (index, id) => {
let new_editing_members_state = members.map(() => false)
new_editing_members_state[index] = false
setEditingMemberName(new_editing_members_state)
}
// BELOW, LOOPS OVER EACH ITEM
const memberItems = members.map((member, index) => {
return (
<MemberItem
member={member}
index={index}
editingMemberName={editingMemberName[index]}
editMemberName={editMemberName}
handleChangeName={handleChangeName}
updateMemberName={updateMemberName}
cancelEditMemberName={cancelEditMemberName}
destroyMember={destroyMember}
/>
)
})
return (
// RENDER THE LIST OF ITEMS
{memberItems}
)
}
// Member.js (Child Component)
export const MemberItem = (
member,
index,
editingMemberName,
editMemberName,
handleChangeName,
updateMemberName,
cancelEditMemberName,
destroyMember
) => {
return (
<div
key={member.id}
>
<div>
{editingMemberName[index] ? (
<input
type="text"
placeholder="Johnny Appleseed"
onChange={handleChangeName}
/>
) : (
<>
<div>
{member.name.substring(0, 1).toUpperCase()}
</div>
<h3>{member.name}</h3>
</>
)}
</div>
<div>
{editingMemberName[index] ? (
<button
onClick={() => updateMemberName(index, member.id)}
>
<CgCheckO size=".75em" />
</button>
) : (
<button
onClick={() => editMemberName(member.id, index)}
>
<FiTool size=".75em" />
</button>
)}
<button>
{editingMemberName[index] ? (
<GiCancel
onClick={() => cancelEditMemberName(member.id, index)}
size=".75em"
/>
) : (
<RiDeleteBinLine
onClick={() => destroyMember(member.id)}
size=".75em"
/>
)}
</button>
</div>
</div>
)
}
Currently, I am getting an error of TypeError: editingMemberName is undefined and a warning of Each child in a list should have a unique "key" prop, but if you see, I do pass in an id into the key property.
In React, props are passed down to function components as a single object.
Your component function assumes props are passed down as separate arguments and not in a single object.
Fixed component definition (note the brackets around the argument list):
MemberItem = ({
member,
index,
editingMemberName,
editMemberName,
handleChangeName,
updateMemberName,
cancelEditMemberName,
destroyMember
}) => { ... }
This method of unpacking properties is called object destructuring.
working with React (but issue is Javascript I think) whereby I am trying to pass an array to a React component, and then within the child component (that consumes the array) - take values out of the array.
What I want to do is access the value: "_label" in my array. I've tried to do various versions of something like: key._label but to no success!
Parent:
<StyledHorizontalAttributes>
{objects[0].attributeCollection.questions.map((question) => (
<FirstRepeatAttributeLabelAssistant key={question.key} />
))}
{console.log(objects[0].attributeCollection.questions)} // returns [StringAttributeModel (below)]
</StyledHorizontalAttributes>
Child:
const FirstRepeatAttributeLabelAssistant = ({ label, assistant, key }) => {
return (
<StyledGroup
as={Row}
>
<StyledLabelWrapper>label</StyledLabelWrapper>
{/* {isGroupedInput && ( */}
<Column
size={12}
/>
<Column>
<StyledAssistantWrapper>assistant</StyledAssistantWrapper>
</Column>
</StyledGroup>
);
};
Array:
Yu forgot pass label to Child component:
<FirstRepeatAttributeLabelAssistant key={question.key} label={question._label} />
And using {} to get value from label:
<StyledLabelWrapper>{label}</StyledLabelWrapper>
Look like, you are trying to access the object _contributions
Then you first need to put it into props:
<StyledHorizontalAttributes>
{objects[0].attributeCollection.questions.map((question) => (
<FirstRepeatAttributeLabelAssistant key={question.key} {...question._contributions} />
))}
</StyledHorizontalAttributes>;
With that spread operator, you will have all the props from the _contributions object:
const FirstRepeatAttributeLabelAssistant = ({ label, assistant, key }) => {
return (
...
);
};
React is mapping duplicate posts
like this
Ideally im just looking to map the likes array.
{myLikes.map(like =>
)}
within the posts, i don't want duplicates posts. How would i achieve that ?
PostList.js
render(){
const {posts, myLikes} = this.props;
return (
<div>
{posts.map(post => (
<div>
{myLikes.map(like =>
<Paper key={post.id} style={Styles.myPaper}>
<PostItem
myLikes={like}
myTitle={this.state.title}
editChange={this.onChange}
editForm={this.formEditing}
isEditing={this.props.isEditingId === post.id}
removePost={this.removePost}
{...post}
// {...like}
/>
</Paper>
)}
</div>
))}
</div>
)
}
}
const mapStateToProps = (state) => ({
isEditingId: state.post.isEditingId,
myLikes: state.post.likes // reducer likes
})
Posts
Likes
This is actually what you told React to do, without realizing it.
I'm assuming that myLikes is an array of numbers, in this case [32, 15].
Your code says (in pseudocode form):
for each post p
for each like l
render the post p with like l
That gives you 2 * 2 = 4 copies.
this is due to nested maps in the PostList component,
you can merge the mylikes and post arrays first and then use map
How to merge multiple arrays
this is how it will work
const results = _.merge(myLikes, posts);
return (
<div>
{results.map(result => (
<Paper key={result.id} style={Styles.myPaper}>
<PostItem
myLikes={result.like}
myTitle={this.state.title}
editChange={this.onChange}
editForm={this.formEditing}
isEditing={this.props.isEditingId === post.id}
removePost={this.removePost}
/>
</Paper>
))}
</div>
);