Exclude An item from mapping - reactjs

I want to explicitly exclude imgvid from mapping and pass it to PostContainer Component.It Causes Rerendering of Component.I want imgvid to pass from PostList to PostContainer.But without this double mappings (in postContainer and postList) Iam unable to correctly fetch my data in the .jsx page.But this double mapping causes rerendering of the .jsx page and it causes doubling of my content in the front page.
<React.Fragment>
<div style={{ marginTop: "10px" }}>
{posts.map(item => (
<PostContainer
isStylefeed={isStylefeed}
likeAccess={likeAccess}
commentAccess={commentAccess}
wowAccess={wowAccess}
yayAccess={yayAccess}
post={item}
imgvid={imgvid}
key={item[ID]}
loadPosts={loadPosts}
currentCommunity={currentCommunity}
currentCommunityID={currentCommunityID}
handlePosts={handlePosts}
getOutfits={getOutfits}
isMember={isMember}
/>
))}
</div>
</React.Fragment>
//PostContainer.jsx
return (
<React.Fragment>
<div>
{imgvid
&& imgvid.map(item => (
<Posts
likeAccess={likeAccess}
commentAccess={commentAccess}
wowAccess={wowAccess}
isStylefeed={isStylefeed}
yayAccess={yayAccess}
handleRedirectOutfitPage={this.handleRedirectOutfitPage}
currentCommunity={currentCommunity}
toggleFlagModal={this.toggleFlagModal}
handleFlaggedPostReasonChange={this.handleFlaggedPostReasonChange}
deletePost={this.deletePost}
handledeleteComment={this.handledeleteComment}
getCurrentProfile={this.getCurrentProfile}
onReadOnlyProfile={this.onReadOnlyProfile}
updatePost={this.updatePost}
handleUpdatePost={this.handleUpdatePost}
toggleUpdate={this.toggleUpdate}
toggleOptions={this.toggleOptions}
handleFlagPost={this.handleFlagPost}
flagModal={flagModal}
post={post}
likesProfile={likesProfile}
followersProfile={followersProfile}
outfits={outfits}
readOnlyProfileModal={readOnlyProfileModal}
modalUpdate={modalUpdate}
postText={text}
postOptions={postOptions}
getAllCommentsByPostId={this.getAllCommentsByPostId}
currentCommunityID={currentCommunityID}
outfitChanged={outfitChanged}
getLatestPost={this.getLatestPost}
toggleMessageModal={this.toggleMessageModal}
messageModal={messageModal}
refData={refData}
showflagModal={showflagModal}
checkFlaggedOrNot={this.checkFlaggedOrNot}
flagged={flagged}
isMember={isMember}
imgvid={item}
email={email}
/>
))}
</div>
</React.Fragment>
);

Related

React.js : index.js:1 Warning: Each child in a list should have a unique "key" prop

I'm doing an app, in the fronted i'm using react, and whenever that i use the map function, i get these errors.
And you would think... Well, that's because you didn't assing any key to your container, and the truth is that, i did... but the errores keeps showing.
Let me show you the code
{specificPhotos.map((photo, i) => {
return (
<>
{/* The Photo */}
<PhotoWrapper key={photo.id}>
{/* For Images */}
{photo.photo.charAt(5) === "i" && (
<img src={photo.photo} />
)}
{/* For Videos */}
{photo.photo.charAt(5) === "v" && (
<>
<video src={photo.photo} />
</>
)}
{/* For Videos Too */}
{photo.photo.charAt(5) === "v" && (
<>
<VideoPlay>
<VideoPlayIcon />
</VideoPlay>
</>
)}
And the other time i used map fn as well
{singlePhoto.comments.map(comment => {
return (
<>
<ContainComment key={comment.id}>
{/* Photo */}
<PresentationImg
style={{ width: "100%", maxHeight: "50px" }}
area="perfil"
>
<CommentPresentation>
<img src={comment.presentation} />
</CommentPresentation>
</PresentationImg>
{/* Body */}
<TheComment>
<h2>
{comment.user} <span>{comment.body}</span>
</h2>
</TheComment>
So, where am i supossed to do with the key? maybe i did something wrong... I don't know, just help me and thanks for your time !
The problem is your second code snippet.
Option 1:
If you can remove the React fragment i.e <></>
Option 2:
However, If the React fragment is serving the purpose of wrapping the elements together, you can replace it with a
<div key={comment.id}><div/>
this means that you can remove the key={comment.id} on the <ContainComment key={comment.id}>
Your key should be on the top most element, which in this case are the fragments. See keyed-fragments
<React.Fragment key={comment.id}>
<ContainComment>
you need to add a key to the fragment right after the return (<>), but unfortunately you can only add a key if it is imported as Fragment (<Fragment key={}></Fragment>), instead of using the short syntax.
As mentioned above, the React fragment <></> is the issue.
Why is this:
const todoItems = todos.map((todo) =>
<li key={todo.id}>
{todo.text}
</li>
);
different from this?
const todoItems = todos.map((todo) =>
<>
<li key={todo.id}>
{todo.text}
</li>
</>
);
Because the fragment needs the key on it (or removed) in the 2nd snippet to prevent the map error.
If you need to keep the fragment to avoid adding an unnecessary div, you could also do:
const todoItems = todos.map((todo) =>
<React.Fragment key={todo.id}>
<li>
{todo.text}
</li>
</React.Fragment>
);
Source: https://reactjs.org/docs/lists-and-keys.html#keys

ReactJS conditional display of elements with map function is returning that my object or key is 'undefined'

Here I have passed my state from one component to another the same way I've done before. And when I console.log the passed state (before I add the map statement in JSX) I get the object im looking for. But when I go inside the return statement I get "cannot map 'undefined'". And at that point the console.log starts returning as undefined. But before I tried to map over the passed prop the console.log was returning the data.Can anyone help me see what im doing wrong?
function Items ({orgList}) {
console.log(orgList.items)
return (
<>
{orgList ?
<div>
{orgList.items.map((item, i) => (
<Card key={i} className= "w-100 m-2">
<CardHeader className="d-flex">
<p>Hello</p>
</CardHeader>
<CardBody>
<p>The Body</p>
<Row>
<Col md="5">
<dl>
<dt>GroupID</dt>
<dd>{item.GroupID}</dd>
<dt>Name</dt>
<dd>{item.name}</dd>
</dl>
</Col>
</Row>
</CardBody>
</Card>
))}
</div>
:
<div>
<PageLoadSpinner inProgress={inProgress} />
</div>
}
</>
)
}
export default Items;**strong text**
Here is the parent Component
function Orgs () {
const [orgList, setOrgList] = useState([]);
useEffect(() => {
loadOrgs();
}, []);
const loadOrgs = () => {
api.MonitoringOrg.list()
.then(response => {
console.log(response)
setOrgList(...orgList, response)
})
.catch(err => console.log(err))
}
return(
<>
<Items orgList={orgList}/>
</>
)
}
export default Orgs;
Errors that include undefined like the one you are observing likely mean one of two things:
(1) The variable is not defined or accessible to the function. This is not the case in your situation as you have shown that the variable is accessible outside of the scope of your conditional. Or,
(2) The render function has not yet evaluated your variable by the time it gets to rendering. This is likely the case in your situation.
I think the second situation is due to a race condition, and I leave the details of that to someone with better knowledge of the React source code to explain.
An easy way to avoid this situation is to update your conditional with the specific keys you will need. This will help prevent the render function from short circuiting your component. This way, your data will not be called upon if a render proceeds without it being there.
Given in your situation that you are drawing on orgList.items in your map function, let's update the code as per the following:
function Items ({orgList}) {
console.log(orgList.items)
return (
<>
{orgList?.items? {/* <------ update this line as seen here */}
<div>
{orgList.items.map((item, i) => (
<Card key={i} className= "w-100 m-2">
<CardHeader className="d-flex">
<p>Hello</p>
</CardHeader>
<CardBody>
<p>The Body</p>
<Row>
<Col md="5">
<dl>
<dt>GroupID</dt>
<dd>{item.GroupID}</dd>
<dt>Name</dt>
<dd>{item.name}</dd>
</dl>
</Col>
</Row>
</CardBody>
</Card>
))}
</div>
:
<div>
<PageLoadSpinner inProgress={inProgress} />
</div>
}
</>
)
}
export default Items;

React Reveal not working for array of data

Can't use React Reveal on array of data with .map() to produce effect from documentation.
https://www.react-reveal.com/examples/common/
Their documentation gives a nice example
<Fade left cascade>
<div>
<h2>React Reveal</h2>
<h2>React Reveal</h2>
<h2>React Reveal</h2>
</div>
</Fade>
I want to produce the same CASCADE effect with my data
<React.Fragment>
{projects.filter(project => project.category === category)
.map((project, index) => {
return (
<ProjectThumb key={index} project={project}
showDetails={showDetails}/>
)
})}
</React.Fragment>
The effect I'm getting is that the entire ProjectThumb component list fades in in one group, I need them to fade in individually and as i scroll. Thanks in advance.
Pass react-reveal props to your React component. It will work.
<Fade left cascade>
<div>
{
projects
.filter(project => project.category === category)
.map((project, index) => (
<ProjectThumb key={index} project={project} showDetails={showDetails} />
))
}
</div>
</Fade>
In your ProjectThumb.js
const ProjectThumb = props => {
return <Whatever {...props}>{...}</Whatever>
}

React-virtualized List selected item styling only fire when scroll up

I'm using React-virtualized to show the data as list.
I add selected styling for list item, it supposes highlight the item once it got click.
The current problem is onClick is fired, but selcted styling only shows when scroll up the list.
List component
<div className={styles.autoSizerContainer}>
<AutoSizer>
{({width, height}) => {
// Selected customer styling only fire after scroll
return (
<List
width={width}
height={height}
rowHeight={50}
rowRenderer={this.renderRow}
rowCount={rowCount}
overscanRowCount={3}
className={styles.list}
/>
)
}}
</AutoSizer>
</div>
List item
private renderRow = ({index, key, style}: ListRowProps) => {
const data = this.props.dataList[index];
return (
<div style={style} key={data.id}>
<div className={styles.listItem}>
<div>data.name</div>
<Item key={data.id}
isDataSelected={this.state.selectedId === data.id}
/> //return true will show selected styling
</div>
</div>
)
};
"react-virtualized": "^9.21.0",
"react": "^16.8.4"
Any ideas are welcome!
Thanks!!!
React-Virtualized will only re-render your component when one of the props provided by ListRowProps changes. It doesn't know that your render method uses this.props.dataList and this.state.selectedId internally. You will need to do one of two things.
Explicitly tell the List to redraw when this.state.selectedId changes. The List exposes an api for this purpose.
Use something like React's Context api to provide the necessary data in a way such that changes can be detected. Something like this should work:
const {Provider, Consumer} = React.createContext<number | null>(null);
<div className={styles.autoSizerContainer}>
<AutoSizer>
{({width, height}) => {
// Selected customer styling only fire after scroll
return (
<Provider value={this.state.selectedId}>
<List
width={width}
height={height}
rowHeight={50}
rowRenderer={this.renderRow}
rowCount={rowCount}
overscanRowCount={3}
className={styles.list}
/>
</Provider>
)
}}
</AutoSizer>
</div>
private renderRow = ({index, key, style}: ListRowProps) => {
const data = this.props.dataList[index];
return (
<Consumer>
{(selectedId) =>
<div style={style} key={data.id}>
<div className={styles.listItem}>
<div>data.name</div>
<Item key={data.id}
isDataSelected={selectedId === data.id}
/> //return true will show selected styling
</div>
</div>
}
</Consumer>
)
};

Spreading props to a list of Components

I'm trying to send a bunch of props to a Component.
In console.logs I noted that everything is working as I expected, every object has its correct value, every spread operation is working. But my Cards doesn't show in the page.
Is this way correct?
return (
<div>
{this.state.articles.forEach((card) => {
<ArticleCard {...card} />
})}
</div>
)
Image showing the problem
Array.forEach does not return anything. You need to use Array.map. Also you should be returning the component to be rendered in the callback.
return (
<div>
{this.state.articles.map((card) => (
<ArticleCard {...card} />
)}
</div>
)
Instead of using forEach, you should use map function on array, and with return keyword to return each and every ArticleCard
return(
<div>
{this.state.articles.map((card) => {
return <ArticleCard {...card} />
})}
</div>
)

Resources