Load a component after getting API fetched data in React.js - reactjs

My components code is like below
componentDidMount = () => {
this.props.dispatch(getCountry());
}
render() {
let rows = this.props.countries.map((item, index) => (//some code here));
return (
<div>
{rows ? (
//components HTML code here
) : (
<img src="loading.gif" alt="Loading ..."/>
)}
</div>
)
}
But the component is loading before API fetched data.

rows is an array hence !rows will still be true. Try this :
return (
<div>
{rows && rows.length ? (
//components HTML code here
) : (
<img src="loading.gif" alt="Loading ..."/>
)}
</div>
)

You can check for rows data since it would be an empty array if not fetched.
return (
<div>
{rows && rows.length ? (
//components HTML code here
) : (
<img src="loading.gif" alt="Loading ..."/>
)}
</div>
)
You can also write your condition like rows && rows.length > 0 same with rows && rows.length. Therows.length if it's empty will resolved to 0 which is false, but if greather than 0 will be true(Typecasting or type conversion).
return (
<div>
{(rows && rows.length > 0 ? (
//components HTML code here
) : (
<img src="loading.gif" alt="Loading ..."/>
)}
</div>
)

Try this componentWillUnmount() {
this.props.countries = []
}, That might help you.

Related

React - Only show item if variable is true

I want to only show each instance of the FeedTag if let soldOut is false. How do I add this condition to each instance of the FeedTag? Each product in the productList has a qty and soldout prop and I only want to show a <FeedTag> where qty !== soldout.
<div>
{productList.length > 0 &&
productList.map((product, i) => {
let soldOut = (productList.qty = productList.soldout);
return (
<FeedTag
data={product}
name={product.headline}
onSelect={(e) => onSelectProduct(e)}
checked={seletedProductList.includes(product._id)}
icon={<img src={helper.CampaignProductImagePath + product.image} alt="" />}
/>
);
})}
</div>
Fix your assignment of soldOut (using ===; I also renamed the variable to available) and use conditional rendering:
...
const available = productList.qty !== productList.soldout;
return (
available && <FeedTag ... />
);
);
Filter out the products that are not sold out first, then map:
<div>
{productList
.filter((product) => product.qty !== product.soldout)
.map((product) => (
<FeedTag
key={product._id}
data={product}
name={product.headline}
onSelect={(e) => onSelectProduct(e)}
checked={seletedProductList.includes(product._id)}
icon={
<img src={helper.CampaignProductImagePath + product.image} alt='' />
}
/>
))}
</div>
Also don't forget the key attribute inside the map.

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>
)
}

How to return React component inside mapping

I just can't figure out the syntax mistake here, but my React components won't render. What am I doing wrong?
return (
shouldShow && (
<div>
{this.props.photos.map(({ url }) => {
return (
this.state.expanded
? <ImageGallery passedProp={url} />
: <AnotherComponent passedProp={url}
)
})}
</div>
)
);
I get the error:
JSX attributes must only be assigned a non-empty expression
EDIT updated full code as requested:
showGallery = () => {
const shouldShow = this.props.photos.length > 0;
return (
shouldShow && (
<div>
{this.props.photos.map(({ url }) => {
return (
this.state.expandedThumbnail
? <ImageGallery imageUrl={urlurlurl}/>
: <button
key={url}
onClick={this.doThis}
>
<img
src={url}
/>
</button>
)
})}
</div>
)
);
};

Conditional Rendering of div in ReactJS?

I'm a newbie to ReactJS. I want to insert a condition in my code below so that when noPeopleText.length > 0, then only should the "no-people-row" div render, otherwise, I do not want this div rendering to the DOM if noPeopleText is an empty string or undefined.
What's the best way do add in a conditional for this?
const peopleMember = (props) => {
const { people, noPeopleText, title } = props;
const hasPeople = Boolean(people && people.length);
const peopleGroup = _.groupBy(people, (person, i) =>
Math.floor(i / 2)
);
return (
<div>
{ hasPeople &&
<SectionHeader
title={title}
/>
}
{ (hasPeople || noPeopleText) &&
<div className="c-team-members">
<div className="container">
{ hasPeople ? _.map(peopleMemberGroups, (members, i) => (
<div className="row" key={i}>
{members && members.map((member, j) => (
<TeamMember
key={j}
name={member.name}
/>
))
}
</div>
)) : //If noPeopleText.length > 0, render div below
<div className="row no-people-row">
<div className="col-xs-12" dangerouslySetInnerHTML={{__html: noPeopleText}} />
</div>
}
</div>
</div>
}
</div>
);
};
You already have conditional rendering in your code. For example:
{ hasPeople &&
<SectionHeader title={title} />
}
This will only render the component SectionHeader if hasPeople evaluates to true. If hasPeople evaluates to false then the whole expression would evaluate to false regardless of the second part of the &&. Thus it is never executed (rendered).
So do you want something like this?
const peopleMember = (props) => {
const { people, noPeopleText, title } = props;
const hasPeople = Boolean(people && people.length);
const peopleGroup = _.groupBy(people, (person, i) =>
Math.floor(i / 2)
);
return (
<div>
{ hasPeople &&
<SectionHeader
title={title}
/>
}
{ (hasPeople || noPeopleText) &&
<div className="c-team-members">
<div className="container">
{ hasPeople ? _.map(peopleMemberGroups, (members, i) => (
<div className="row" key={i}>
{members && members.map((member, j) => (
<TeamMember
key={j}
name={member.name}
/>
))
}
</div>
)) : (noPeopleText.length > 0) &&
<div className="row no-people-row">
<div className="col-xs-12" dangerouslySetInnerHTML={{__html: noPeopleText}} />
</div>
}
</div>
</div>
}
</div>
);
};
I think you can just use a nested ternary operator:
{ hasPeople
? //mapping
: noPeopleText.length > 0
? <div className="row no-people-row">
<div className="col-xs-12" dangerouslySetInnerHTML={{__html: noPeopleText}} />
</div>
: null
}

react render div if loop was empty

I am rendering a list and I want to show an info that data was not loaded.
Here is my code:
<div className="dashboard-table dashboard-table-done">
<div className="dashboard-table-title dashboard-table-title-done">Chamadas encerradas</div>
{ this.state.data && this.state.data.map(attendInfo =>
attendInfo.close && (
<DashboardAttend {...attendInfo} />
)
)}
If attendInfo.close then renders <DashboardAttend>
If no one was rendered I want to render a message saying that no one data was rendered like:
<div>No one data was found</div>
I can't use this.state.data because the field close can be null and length can be higther than 0
How about something like this
render(){
const dataForRender = this.state.data? this.state.data.filter((attendInfo) => {
return attendInfo.close;
}): [];
return (
<div className="dashboard-table dashboard-table-done">
<div className="dashboard-table-title dashboard-table-title-done">
Chamadas encerradas
</div>
{
dataForRender.length>0 ? dataForRender.map(attendInfo =>
(
<DashboardAttend {...attendInfo} />
)
): <div>No one data was found</div>
}
</div>
);
}
I think what you are asking is if state.data is empty or contains no elements, then you want to write:
<div>No one data was found</div>
You can do this by simple adding another bit to the end:
{ (!state.data || !state.data.length) && <div>No one data was found</div> }
So in position it would look something like:
<div className="dashboard-table dashboard-table-done">
<div className="dashboard-table-title dashboard-table-title-done">Chamadas encerradas</div>
{ this.state.data && this.state.data.map(attendInfo =>
attendInfo.close && (
<DashboardAttend {...attendInfo} />
)
)}
{ (!state.data || !state.data.length) && <div>No one data was found</div> }

Resources