How to add Element between react children with Some condition? - reactjs

I need to add element between each children when some props values satisfied
how to do that
"only add element if the prop value is space is true"
now i did like this
const style={
height:"10px"
}
if(this.props.space){
style.width=30;
}
render(){
return(
{React.Children.map(children, (child, i) => {
return (
<React.Fragment>
<span style={style}></span>
<React.Fragment>{child}</React.Fragment>
</React.Fragment>
);
})}
)
}

So is it the span you only want if space is true?
Then you could do something like this
{React.Children.map(children, (child, i) => {
return (
<React.Fragment>
{this.props.space && <span style={style}></span>}
<React.Fragment>{child}</React.Fragment>
</React.Fragment>
);
})}
The concept is explained here https://reactjs.org/docs/conditional-rendering.html#inline-if-with-logical--operator
It works because true && expression will evaluate to expression, and false && expression will evaluate to false.

Span is an inline element and doens't take width and height. You can instead return a div element conditionally and and align the child and the div element horizontally like
function App({ children, space }) {
const style = {
height: "10px",
width: "30px",
backgroundColor: "red",
display: "inlin"
};
return (
<React.Fragment>
{React.Children.map(children, (child, i) => {
return (
<React.Fragment>
<div style={{ display: "flex" }}>
{space ? <div style={style} /> : null}
<div>{child}</div>
</div>
</React.Fragment>
);
})}
</React.Fragment>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<App space>
<div>Hello</div>
</App>,
rootElement
);
Working demo
However conditionally adding an element to provide space to the left doesn't seem to be a good idea. You can instead add class and add property like margin-left or add a style
return (
<React.Fragment>
{React.Children.map(children, (child, i) => {
return (
<React.Fragment>
<div style={{marginLeft: '30px'}}>{child}</div>
</React.Fragment>
);
})}
</React.Fragment>
);

Related

Nothing was returned from render. When using a ternery operator

I am trying to conditional render a part of a JSX element based on a conditional (whether linkShareLogs is truthy or not. I am using a ternery operator for this.
Currently I receive this error:
Uncaught Error: CodeLinkShareLogs(...): Nothing was returned from render. This usually means a return statement is missing. Or, to render nothing, return null.
Here is how the JSX component is called:
if (selected) {
<CodeLinkShareLogPanel
linkShareLogs={linkShareLogs}
isBannerHidden={isBannerHidden}
showSlackPrompt={showSlackPrompt}
setShowSlackPrompt={setShowSlackPrompt}
/>;
} else {
return (
<div
className="flex flex-col"
style={{ height: `calc(100vh - ${offset}px)`, overflow: "auto" }}
>
{showSlackPrompt && <CodeLinkSlackPrompt setShowSlackPrompt={setShowSlackPrompt} />}
</div>
);
}
Here is the relevant component I am trying to render.
export function CodeLinkShareLogPanel({
linkShareLogs,
[...]
}: props) {
return (
<div>
{showSlackPrompt && <CodeLinkSlackPrompt setShowSlackPrompt={setShowSlackPrompt} />}
{linkShareLogs ? ( //begin ternery
sortShareLogs(linkShareLogs).map((log: LinkShare, key) => (
<div key={key} className="text-black">
[...]
</div>
))
) : (
<div>
This link hasn't been shared yet.
</div>
)}
</div>
);
}
Try this way. In the first conditional you didnt return anything at all which is why u got that error
{
selected ? (
<CodeLinkShareLogPanel
linkShareLogs={linkShareLogs}
isBannerHidden={isBannerHidden}
showSlackPrompt={showSlackPrompt}
setShowSlackPrompt={setShowSlackPrompt}
/>
) : (
<div
className="flex flex-col"
style={{ height: `calc(100vh - ${offset}px)`, overflow: "auto" }}
>
{showSlackPrompt && (
<CodeLinkSlackPrompt setShowSlackPrompt={setShowSlackPrompt} />
)}
</div>
)
}

My console are screaming about the React KEY but I didn't see the error. Can you help me?

I see this warning in console. But where is my mistake? I have Warning: Each child in a list should have a unique "key" prop. but I put the KEY PROP in all components what I render with map function.
One warning in this map function:
{data && data.map(item => (
<Card key={item.id}>
<CardTitle>{item.title}</CardTitle>
<CardPrice>{item.price}</CardPrice>
<CardDescription>{item.description}</CardDescription>
<CardItems>
{item.benefits.map(benefitsItem => (
<CardItem>
<CheckCircleIcon />
<CardItemText>{benefitsItem}</CardItemText>
</CardItem>
))}
</CardItems>
<StyledPopup
trigger={<CardButton className="BlackButton">Замовити сайт</CardButton>}
modal
nested
lockScroll
>
{close => (
<div className='modal'>
<button className="closeModal" onClick={close}>×</button>
<Feedback
isPlan={{
name: item.title,
description: item.description,
price: item.price
}}
/>
</div>
)}
</StyledPopup>
</Card>
))}
And Other warning in this component:
<Navigation>
{cards && cards.map(item => renderLinks(item))}
</Navigation>
<CardsWrapper>
{cards && cards.map(item => renderCard(item))}
</CardsWrapper>
There is the render functions.
const renderCard = (cardData) => {
if(cardData.cardId === activeCard){
return(
<Card key={cardData.cardId}>
<ImageWrapper>
<Image src={cardData.cardImage} />
</ImageWrapper>
<CardInfoWrapper>
<CardTitle>{cardData.cardTitle}</CardTitle>
<CardDescription>
{cardData.cardDescription}
</CardDescription>
<Pluses>
{cardData.cardOpportunities && cardData.cardOpportunities.map(opportunity => (
<Plus>
<Ok><CheckCircleIcon /></Ok>
{opportunity}
</Plus>
))}
</Pluses>
</CardInfoWrapper>
</Card>
)
}
}
And finnely
const renderLinks = (cardData) => {
if(cardData.cardId === activeCard) {
return(
<div key={cardData.cardId}>
<NavigationItem
className="navigationLink"
width={cardData.cardLinkWidth}
active
>
{cardData.cardLink}
</NavigationItem>
</div>
)
} else {
return(
<div key={cardData.cardId}>
<NavigationItem
className="navigationLink"
width={cardData.cardLinkWidth}
onClick={() => linkClickHandler(cardData.cardId)}
>{cardData.cardLink}</NavigationItem>
</div>
)
}
}
Looks like there's a missing key prop on line 10 at
{item.benefits.map(benefitsItem => (
<CardItem>
CardItem needs a key prop.
Each CardItem within the Card also needs it's own key as there are multiple CardItem components mapped from the benefits array. i.e <CardItem key={benefitsItem.id}/>

how can I add any event to a specific part of component ? react

I have list of data that render it with map - I need to add an event just in one of the item from that list.
const UserModal = (props) => {
const {user,setUser} = props ;
const list = [,{id:3,text:'گفت وگو ها',icon:<BsChat />},{id:5,text:'خروج',icon:<BiExit />},];
/this is my list for making navigation bar
return (
<div className={style.main}>
<div style={{bordeBottom:'1px solid black'}}>
<BiUser />
<p>{user.username}</p>
</div>
{ //this is where I render a list to show and make component
list.map((item)=>
<div key={item.id}>
{item.icon}
<p>{item.text}</p>
</div>)
}
</div>
);
};
export default UserModal;
this my code and for example I need to add an event on specific object that has id=5 in that list .
how can I do that
I don't know if there is some sort of built-in solution for this, but here is a simple workaround:
I changed a few things for simplicity's sake
The important part is the if statement with checks if item ID is 5 then if so adds a div with the desired event
function App() {
const list = [
,
{ id: 3, text: "comonent 3" },
{ id: 5, text: "comonent 5 (target)" }
];
return (
<>
<h1>Hello world<h1/>
{list.map((item) => (
<div key={item.id} style={{ backgroundColor: "red" }}>
<p>{item.text}</p>
{item.id == 5 ? (
<div
onClick={() => {
alert("This component has a event");
}}
>
{" "}
event
</div>
) : (
<></>
)}
</div>
))}
</>
);
}
const UserModal = (props) => {
const {user,setUser} = props ;
const myEvent = () => alert('event fired');
const list = [,{id:3,text:'گفت وگو ها',icon:<BsChat /> , event : myEvent},{id:5,text:'خروج',icon:<BiExit />},];
/this is my list for making navigation bar
return (
<div className={style.main}>
<div style={{bordeBottom:'1px solid black'}}>
<BiUser />
<p>{user.username}</p>
</div>
{ //this is where I render a list to show and make component
list.map((item)=>
<div key={item.id}>
{item.icon}
<p onClick={item.event}>{item.text}</p>
</div>)
}
</div>
);
};
export default UserModal;
list.map((item, i)=> (
item.id == 5 ?
<div onClick={handleClick} key={i}></div>
:
<div key={i}></div>
)

Remove previous content when new one is rendered through a condition (React)

I have a navbar that uses eventKeys to switch between the buttons
const CustomNav = ({ active, onSelect, ...props }) => {
return (
<Nav
{...props}
activeKey={active}
onSelect={onSelect}
style={{ marginBottom: "15px" }}>
<Nav.Item eventKey='all'>All</Nav.Item>
<Nav.Item eventKey='movies'>Movies</Nav.Item>
<Nav.Item eventKey='shows'>Shows</Nav.Item>
<Nav.Item eventKey='people'>People</Nav.Item>
</Nav>
);
};
I did this:
const Content = () => {
if (this.state.active === "all") {
return (
<div>
{trending.results &&
trending.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
} else if (this.state.active === "movies") {
return (
<div>
{trendingMovies.results &&
trendingMovies.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
}
};
Called it here:
return (
<div className='Home'>
<FlexboxGrid justify='center'>
<Panel bordered header='Trending today!'>
<CustomNav
className='customNav'
appearance='subtle'
active={active}
onSelect={this.handleType}
/>
<Content />
<Pagination
{...this.state}
style={{ marginTop: "15px" }}
maxButtons={5}
size='sm'
pages={totalPages}
activePage={this.state.activePage}
onSelect={this.handlePage}
/>
</Panel>
</FlexboxGrid>
</div>
);
}
}
To display the correct data for each tab, but when I'm on the movies tab it shows all the data from the first "all" tab + data on the "movies" tab. I wanna show each data individually corresponding to the correct tab which is controlled by "this.state.active". Tried a switch statement too and that did not work
you are using the arrow syntax
const Content = () => { ... }
and also using this.state variable in your code !!!
if you want to use this.state, then you want to use the class syntax, like
class Content extends React.Component { ... }
but don't mix the two styles.
what you are probably wanting to do is to send the active variable as a prop
try:
const Content = ({active}) => {
if (active === 'all') {
return (...)
} else if (active === 'movies') {
return (...)
}
return null
}
and where you are calling the component you send the active value in as a prop
<Content active={active} />
Note also that you are using the variables trending and trendingMovies and it is unclear where those come from, you may need to send those via props also.
Now you can also leave the if..else logic outside of your Content component like so
const Content = ({myTrending}) => {
return (
<div>
{myTrending.results &&
myTrending.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
}
and then where you call that component you have
<Content
myTrending={active === 'all' ? trending : trendingMovies}
/>
You need to pass active and other variables as props to the Content component, since it doesn't access them otherwise:
const Content = ({active, trending=[], trendingMovies=[]}) => {
if (active === "all") {
return (
<div>
{trending.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
} else if (active === "movies") {
return (
<div>
{trendingMovies.results.map((i) => (
<React.Fragment key={i.id}>
<p>{i.title}</p>
</React.Fragment>
))}
</div>
);
}
};
return (
<div className='Home'>
<FlexboxGrid justify='center'>
<Panel bordered header='Trending today!'>
<CustomNav
className='customNav'
appearance='subtle'
active={active}
onSelect={this.handleType}
/>
<Content active={this.state.active} trending={this.state.trending} trendingMovies={this.state.trendingMovies} />
<Pagination
{...this.state}
style={{ marginTop: "15px" }}
maxButtons={5}
size='sm'
pages={totalPages}
activePage={this.state.activePage}
onSelect={this.handlePage}
/>
</Panel>
</FlexboxGrid>
</div>
);
}
}

React material-ui, grid list cannot render grid items

export interface FlatsGridProps {
flats: IClusterFlats[];
}
export const FlatsGrid: React.StatelessComponent<FlatsGridProps> = (props: FlatsGridProps) => {
if (props.flats.length === 0) {
return (<div> empty </div>);
}
return (
<div style={styles.root}>
<GridList
cols={2}
style={styles.gridList}
cellHeight={180}>
{props.flats.map((f, i) => {
<div key={i}> element </div>
})}
</GridList>
</div>
)
};
When I render GridList control it throws exception
Cannot read property 'props' of null in GridList.js
View from console below.
I think you need to return the child from the map. The grid.js complains about its child being undefined.
<GridList
cols={2}
style={styles.gridList}
cellHeight={180}>
{props.flats.map((f, i) => {
return (<div key={i}> element </div>)
})}
</GridList>

Resources