How to pass a html template through props to a react component? - html

I have a popup up window react component. I want to pass in templates to the component via props.
Here is an example of my popup
popup = (
<div>
<Popup text='This is a popup'
popupEl={ popupEl }
/>
</div>
);
The popup component works if the popupElements value is a button on its own, or a list of checkboxes. But I want to pass in an entire template. Unfortunately the popupElements prop is seen as undefined when I try to do so.
Here is a very basic example of a template I want to pass in. Is there something I'm missing here?
popupEl = (
<div>
<div>
<h1> hi </h1>
</div>
<div>
<button>CLOSE</button>
</div>
</div>
);

The popupEl should be a function which returns JSX,
popupEl = () =>
<div>
<div>
<h1> hi </h1>
</div>
<div>
<button>CLOSE</button>
</div>
</div>
);

Related

State in React component not setting data when the browser (tab) is refreshed

I have this simple react component that gets data from an API (fetch called in UseEffect), and displays it using HTML. When I refresh the page, all html disappears from the page and it goes blank. What's peculiar is that when I instead make some changes in the code editor and let react autoupdate the page after saving, it displays everything just fine.
Here's the code snippet for the component:
export function AgentCard(props){
console.log("agentcard function");
const [agentData,setAgentData] = useState({});
useEffect(()=> {
console.log('running useEffect')
axios.get('https://valorant-api.com/v1/agents/').then(res=>{
var agentRes;
for (const agent of res.data['data']){
if (agent['displayName'] === props.agentName){ agentRes = agent}
}
setAgentData(agentRes);
console.log(agentData)
})
},[])
return(
<div className='AgentCard'>
<h2>{agentData['displayName']}</h2>
<img src={agentData['displayIcon']}></img>
<div className='AgentCardBody'>
<div className='AbilitiesBar'>
<img src={agentData['abilities'][0]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][1]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][2]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][3]['displayIcon']} className='AbilitiesIcon'></img>
</div>
</div>
</div>
)
After some digging and logging, what I found is that when I refresh the page, the state (agentData), is saved to this:
https://imgur.com/a/QzfIdpm
and get the following error in the console:
https://imgur.com/a/H7gLiTQ
But once I make any change to the editor and let react autorefresh, the logs show that the state agentData has the right data object pulled from the API.
Also, this only happens when I have the following part of the code running
<img src={agentData['abilities'][0]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][1]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][2]['displayIcon']} className='AbilitiesIcon'></img>
<img src={agentData['abilities'][3]['displayIcon']} className='AbilitiesIcon'></img>
Once I comment this out, everything displays correctly even after a browser refresh
I know the way I've posed the question is confusing, but I'm new to front end development and don't really know what I'm supposed to look for here.
Probably because agentData.abilities returns undefined (remember that you have an empty object that is asynchronously populated), but you're trying to access it in your template as if an array is present.
You can solve this easily if you conditionally render those <img> elements when agentData.abilities is not undefined, i.e.:
return(
<div className='AgentCard'>
<h2>{agentData['displayName']}</h2>
<img src={agentData['displayIcon']}></img>
<div className='AgentCardBody'>
{agentData.abilities && (
<div className='AbilitiesBar'>
<img src={agentData.abilities[0].displayIcon} className='AbilitiesIcon' />
<img src={agentData.abilities[1].displayIcon} className='AbilitiesIcon' />
<img src={agentData.abilities[2].displayIcon} className='AbilitiesIcon' />
<img src={agentData.abilities[3].displayIcon} className='AbilitiesIcon' />
</div>
)}
</div>
</div>
)
Even better: you can simply iterate through the first 4 entries in agentData.abilities to keep your DOM a bit simpler:
return(
<div className='AgentCard'>
<h2>{agentData['displayName']}</h2>
<img src={agentData['displayIcon']}></img>
<div className='AgentCardBody'>
<div className='AbilitiesBar'>
{agentData.abilities && agentData.abilities.slice(0,4).forEach(ability => (
<img src={ability.displayIcon} className='AbilitiesIcon' />
)}
</div>
</div>
</div>
)

How can I select one item from data in json array by id in NEXT.js

I'm very new to Next.js and are fetching data from an api. I have a list of movies and I want to select one movie and show that movies image on a new page. I guess I have to use the objects id, but I don't know how. This is what I have so far:
Here is my code from starting page:
<div className="movies">
{props.movies.map(movie => (
<div>
<p>{movie.name}</p>
<Link href={`/detailPage?movieId=${movie.image}`}>
<img src={movie.image}></img>
</Link>
</div>
))}
And here is the code from detail page:
<section>
<div>
<img src={movieId.image}></img>
</div>
</section>
You need to get the object you are trying to display from the array. You can do something like this:
const movie = props.movies.find((m) => m.id === idOfTheMovieYouWant);
return (
<section>
<div>
<img src={movie.image} />
</div>
</section>
);

Calling the CSS style from typescript append it to html file

On button click function CSS style to be called with in the TS file
html code:
<div class="overlay-loader">
<div *ngIf="isLoading" class="loader"></div>
<p *ngIf="results">{{ results | json }}</p>
<p *ngIf="error">Error: {{ error | json }}</p>
</div>
<p>
<button (click)="getResult()">Get result</button>
</p>
Link which i have tried:https://stackblitz.com/edit/angular-loader-kspfhg?ctl=1&embed=1&file=app/app.component.html&view=editor
After clicking the button overlay-loader css class to be loaded and once data get fetched css overlay-loader to be dissaper
Use ngClass to add a class conditionally:
<div [ngClass]="{'overlay-loader': isLoading}">

Display HTML code in text box

I am having a text box which I am filling from the Json response as below
<div class="gadget-body" style="height:100px">
<label>{{ textData}}</label>
</div>
But now my Json is returning html code with <p> and <h1> tags. I am binding the response, but it is displaying with <p> and <h1> tags instead of applying it.
The simple and easiest way is use innerhtml tag
<div class="gadget-body" >
<div [innerHTML]="textData">
</div>
</div>
Maybe have a function like this :
function htmlToPlaintext(text) {
return text ? String(text).replace(/<[^>]+>/gm, '') : '';
}
and then you'd use:
<div class="gadget-body" style="height:100px">
<label>{{ htmlToPlaintext(textData) }}</label>
</div>

How change component html template in angular 2?

For example I have this component with a simple template:
<div>
<h2>Hello!!!</h2>
</div>
and I want to add this new template tag:
<div>
<h2>Hello!!!</h2>
<div class = "new-tag">
</div>
</div>
How can I do this?
Thanks.
Use a structural directive like *ngIf
<div>
<h2>Hello!!!</h2>
<div *ngIf="showNew" class = "new-tag"></div>
<button (click)="showNew = true">click me</button>
</div>