ReactJS : Render dynamic child elements inside a custom component - reactjs

I've created a generic component which renders dynamic content. Idea is to render whatever child elements are provided inside the custom component. Code snippet below:-
<DropDownMenu {...profileDropDown}>
<div className="profile-drop-down-settings">
profileProps.map(function(data, index) {
<span>{data}</span>
});
</div>
</DropDownMenu>
Dropdown component (render part) :-
render() {
const config = this.props;
return (
<div class="drop-down-menu">
{this.props.children}
</div>
)
}
Now the issue is, I'm not able to run the map function. It throws an error stating it can't access the data variable. I'm new to react, am I missing anything?

I've setup a simple sandbox to showcase what you're trying to do.
In essence:
App renders Container which is given children by App
the logic for how the children are constructed are controlled by App
Container simply renders those children as is
Hope this example is a replica of what you're trying to achieve

you can try this,
<DropDownMenu {...profileDropDown}>
<div className="profile-drop-down-settings">
{ profileProps.map(function(data, index) {
return <span{data}</span>
}); }
</div>
</DropDownMenu>

Related

NextJS can't figure out why nothing renders from simple prop passing to display a p tag? (Data fetching and displau)

I'm doing some work in NextJS and I needed to render a card so I created the api endpoint setup the query debugged incorrect client state on the page and now it appears that my state variables are correct but I am still not rendering what I would expect.
I'm trying to render a JSON object that looks like this:
[{"id":"cla02oxnl0000txe0vzncxq7o","creator":"cl9x4lmhv00021snptuymv0vr","broken_item":"","issue_desc":"","loc":"","active":true,"prio":"Low"}]
And I can see a valid JSON object in the list of tickets I want to render:
Client side in the console by logging the tickets array.
But I must have some syntax or misunderstanding of how I'm allowed to render here is my code for the page render:
if (!currentSession) {
return (<div> No Session</div>)
}
return (
<div>
{console.log(tickets)}
{tickets.map(({creator,broken_item, issue_desc, loc, prio,active}) => {
<TicketGUI creator={creator} broken_item={broken_item} issue_desc={issue_desc} loc ={loc} prio={prio}/>
})}
</div>
)
And the component that is trying to render it's own props just looks like this:
export default function TicketGUI(props){
return <p> {props} </p>
}
I had the syntax slightly off but my main issue is that I forgot to return something inside the anonymous function inside the map. This will fix the issue and render:
return (
<div>
{}
{tickets.map(
({creator,broken_item, issue_desc, loc, prio,active,creatorName}) => {
return(
<li key={listLength++}>
<TicketGUI creator={creator} broken_item={broken_item} issue_desc={issue_desc} loc ={loc} prio={prio} active={active} name={creatorName}/>
</li>
)
}
)}
</div>
)

Background Image not showing in react production app, showing normally in development

I have a component 'Countries' that shows a list of countries. It loops a JSON object with country names and paths to their flag images, then passes those as props to a Component 'SingleCountry' who in turn displays them.
Relevant part of component 'Countries':
//this is inside return() statement
<div className="country-list">
{
_.map(countries[region], (value, key)=>{
const picture = require(`../../img/flags/${value.picPath}`);
return(
<SingleCountry name={value.name} picture = {picture} countryId={key} key={key}
region={region}/>
)
})
}
</div>
Relevant part of the component 'SingleCountry':
//this is inside return() statement
<div className="single-country">
<div className="flag" style ={{backgroundImage: `url(${picture})`}}></div>
<div className="country-name">{name}</div>
</div>
</div>
The above is working well in development. You can see a picture here (along with the inspection):
https://imgur.com/CirT4YW
However, it is not working in production. You can see a picture here: https://imgur.com/nuX7rKu
Any help is appreciated.

React - component will not render in foreach loop?

I have a small application when you open a tab the React Route redirects to the given component (container). And from the container i want to render the child components. I use the foreach loop to go through a list that has the props that need to be given to the child. However, the child doesn't get rendered.
I don't want to use map because i use libraries that depend on the list class.
render() {
return (
<div>
{this.state.list.ForEach((element) =>
<ChildComponent childName={element.name}
}
</div>
);
}
}
You are confusing Array.forEach with Array.map. forEach does not return anything. The correct way is:
<div>
{this.state.list.map((element, index) =>
<ChildComponent key={index} childName={element.name} />
)}
</div>
map converts the given element into another element, a component in this case. The result of calling map is an array of components that is then rendered. forEach always returns undefined therefore the result of your code is the same as writing:
<div>
{undefined}
</div>
Note that key is also necessary when rendering lists of components.

How can I render a <template /> tag with react?

Sometimes you might need to render web-components from your react app.
Web-components often use a special <template> ... </template> tag.
But if I try to render such markup with react like this:
render() {
return (
<template>
<div>some content</div>
</template>
)
}
then my web-components don't work correctly.
The reason is that JSX does a different job than what the <template /> tags exists for. The idea of a template tag is to not render its children and pretty much handle it like unparsed text (the browser actually parses it just to make sure its valid html, but does nothing more)
But when you write this in JSX:
return (
<template>
<div>some content</div>
</template>
)
you're basically instructing react to create a 'template' element and then create a 'div' element and then to append this div to the template as a child.
So under hood this happens:
const template = document.createElement('template')
const div = document.createElement('div')
const text = document.createTextNode('some text')
div.appendChild(text)
template.appendChild(div)
But what you want is to set the contents of the <template /> as a string. You can use innerHTML for that.
Solution
One solution would be:
render() {
return (
<template
dangerouslySetInnerHTML={{
__html: '<div>some content</div>'
}}
/>
)
}
Now you're asking react to create all those children tags as node elements but letting the browser decide what to do with them.
Nicer solution
You might not want to use dangerouslySetInnerHTML all the time. So let's create a helper component:
function Template({ children, ...attrs }) {
return (
<template
{...attrs}
dangerouslySetInnerHTML={{ __html: children }}
/>
);
}
Now any time you need to use a template you can use it like this:
render() {
return (
<Template>
{'<div>some content</div>'}
</Template>
)
}
Don't forget to put the inner content in quotes, because it should be a string.
I know that this question has already an answer, but there is another, I guess simpler solution to do that creating hoc (Higher Order Component).
Just create new "component" like this:
// hoc/Template.js
const template = props => props.children
export default template
and then you can use it in your project this way:
import './hoc/Template.js'
...
render() {
return (
<Template>
{'<div>some content</div>'}
</Template>
)
}
Newer version of react has already build it such a component, so you can achieve same thing without creating component.
import { Fragment } from 'react'
...
render() {
return (
<Fragment>
{'<div>some content</div>'}
</Fragment>
)
}
This is actually a bug in React! https://github.com/facebook/react/issues/19932
When the native browser parses the <template> tag, it appends all children to the template's content fragment, instead of adding them as children. So a template should never actually have any children.
However, if you programmatically build the DOM (the way react-dom does), then the template will have an empty content fragment, since all children are added as children. This is why web components will not behave properly with these templates.
Here's an example of the problem too: https://codesandbox.io/s/new-sun-8l62o?file=/src/App.tsx:1056-1118
The easiest workaround is to use dangerouslySetInnerHTML, like so:
<template dangerouslySetInnerHTML={{ __html: `
<p> Some text </p>
` }} />
This is limited by the fact that you can only supply raw HTML (no custom React elements). However, since you're using the <template> tag in the first place, it seems highly unlikely that you'd also be using React within the template.

ReactJs: render a collection of dynamic components

I'm rather new to react.js and I wonder if it's possible to render a collection of different components with React?
For example I have a ContainerComponent class with a property childComponents which I want to use like this:
var childComponents = [];
childComponents.push(<TextComponent text={this.props.text} />);
childComponents.push(<PictureComponent src={this.props.image} />);
return (
<ContainerComponent
title={this.props.title}
innerComponents={childComponents} />
)
So the problem is that I can't call child components' render function in loop to generate single output of all children. How could render method of ContainerComponent look like?
Thanks!
Place all the components like you would normally do:
render() {
return (
<div>
{this.props.innerComponents}
</div>
);
}
Normally, the following code should work fine for your needs:
<ContainerComponent
title={this.props.title}
>
<TextComponent text={this.props.text} />
<PictureComponent text={this.props.image} />
</ContainerComponent>

Resources