I am trying map through an object with the goal to render the key and their value inside a p tag. I am having the error message object are not valid react child.
How can I overcome this error?
<div className="d-flex flex-wrap">
{
Object.keys(features).map((item,index) => {
console.log('type',item);
console.log(features[item]);
return <p key={item} className="fw-bold bg-light fs-6 text-primary m-1 p-2">{{[item]:features[item]}}</p>
})
}
</div>
This error is because the code
{{[item]:features[item]}}
actually results to an object. So child of <p> tag is an object. You can solve it by using Template literals inside <p> tag
<div className="d-flex flex-wrap">
{
Object.keys(features).map((item,index) => {
console.log({[item]:features[item]});
console.log(features[item]);
return <p key={item} className="fw-bold bg-light fs-6 text-primary m-1 p-2" >{`{${item}: ${features[item]}}`}</p>
})
}
</div>
In this section of React doc, it is said that:
You can put any valid JavaScript expression inside the curly braces in JSX
Moreover {[item]:features[item]} itself is not a valid expression, according to this list
So instead, you have to embed 2 expressions, item and features[item]
return (
<p key={item} className="fw-bold bg-light fs-6 text-primary m-1 p-2">
{item}: {features[item]}
</p>
)
It is because of the double brackets in your code
Use only one brackets like this
{[item]:features[item]}
Following is JSON
{[item]:features[item]}
If you meant to render the JSON as a string then do like this.
JSON.stringify({[item]:features[item]})
Do it like this
Object.keys(features).map((item) => {
return <p> {item} : {features[item]}</p>
}
Related
I have a select component that doesn't change it's placeholder when I'm clicking its options. It's wrapped around on another component that serves as the outline of like its title. paragraph and then the select component. I also use it on another select component and it also doesn't work. I am pretty sure it changes it value since I checked the state and also the functionality works excpect the changing of the so called placeholder. This is the original outline which works.
<div className={`flex flex-col col-span-6`}>
<div className="flex items-center mb-1">
<h2 className='text-sm'>TYPE OF FLIGHT ANF REGION</h2>
<FontAwesomeIcon icon={faGlobe} className="text-[#2B8E9B] ml-2" />
</div>
<p className='text-xs mb-3'>Choose a type of flight, either DOMESTIC or INTERNATIONAL, and pick which region your coming.</p>
<div className={`grid grid-cols-2 gap-4`}>
<FlightTypeComponent flights={domestic} flightLocalType={"domestic"} {...{flightType, locationsFilter, flightTypeClick ,regionSetter}}/>
<FlightTypeComponent flights={international} flightLocalType={"international"} {...{flightType, locationsFilter, flightTypeClick ,regionSetter}}/>
</div></div>
This is the current outline which doesn't work:
<TwoComponents title={"TYPE OF FLIGHT ANF REGION"} icon={faGlobe} colSpan={"col-span-6"} childrenCss={"grid-cols-2"} paragraph={"Choose a type of flight, either DOMESTIC or INTERNATIONAL, and pick which region your coming."}>
<FlightTypeComponent flights={domestic} flightLocalType={"domestic"} {...{flightType, locationsFilter, flightTypeClick ,regionSetter}}/>
<FlightTypeComponent flights={international} flightLocalType={"international"} {...{flightType, locationsFilter, flightTypeClick ,regionSetter}}/>
</TwoComponents>
The wrapper in question. I both included both components even if I only showcased the TwoComponents incase of any errors or bad practices.
const EachComponentOutline = () => {
const TwoComponents = ({children, title, paragraph, icon, colSpan, childrenCss}) => {
return (
<div className={`flex flex-col ${colSpan}`}>
<div className="flex items-center mb-1">
<h2 className='text-sm'>{title}</h2>
<FontAwesomeIcon icon={icon} className="text-[#2B8E9B] ml-2" />
</div>
<p className='text-xs mb-3'>{paragraph}</p>
<div className={`grid ${childrenCss} gap-4`}>
{children}
</div>
</div>
)}
const OneComponent = ({children, title, icon, paragraph, colSpan}) =>
(
<div className={`flex flex-col ${colSpan}`}>
{icon ? (
<div className="flex mb-1">
<h2 className='text-sm'>{title}</h2>
<FontAwesomeIcon icon={icon} className="text-[#2B8E9B] ml-2" />
</div>
)
: (<h2 className='text-sm mb-1'>{title}</h2>)
}
<p className="text-xs mb-3">{paragraph}</p>
{children}
</div>
)
return {TwoComponents, OneComponent}
}
picture of the placeholder since I'm not sure if "placeholder" is the right term
I answered it but I don't know why and I hope someone can better explain it. Instead of trying to create two components on a single function. You create each component in its own separate function so basically like removing the overall parent function for both TwoComponent and OneComponent. I think using a custom hook would return data and not a whole component so it's better to export and import it.
In my vue app, I get some JSON from my API, I am then computing that returned data and sorting it via one of it's attributes, I am then wanting to then resort it every time that attribute is updated on the client side, I thought it would be enough to add `v-model="tag.weight" to the input but apparently not? What am I doing incorrectly?
<div class="mt-6" v-if="this.sortedTags">
<div class="w-full flex justify-between pb-2 border-white">
<div class="w-1/3 p-4 font-black">Tag</div>
<div class="p-4 font-black">Active</div>
<div class="p-4 font-black">Weight</div>
</div>
<div class="w-full flex justify-between" v-for="tag in this.sortedTags" :key="tag.id">
<div class="w-1/3 p-4">{{ tag.tag }}</div>
<div class="p-4"><input type="checkbox" /></div>
<div class="p-4"><input type="text" v-model="tag.weight" size="3" class="text-black"/></div>
</div>
</div>
computed: {
...mapState(['admin']),
sortedTags() {
return this.admin.tags.sort(function(a, b) {
a.weight - b.weight;
});
}
}
What I was hoping for what the 1) if entered a number into the weight field that is bound tag.weight it would order it based on that input, and 2) When I add new object to the data, it would resort it.
I got similar result when omitting the return, it will give you response, but re-sorting won't work.
Therefore, just use return a.weight - b.weight; instead of a simple a.weight - b.weight;
Detailed explanation : https://stackoverflow.com/a/38159151/3256489
I need to return the following code in ReactJS x amount of times. I am trying to populate a card with names based on how many people there are in a team.
So if x was 5, I would need that to appear 5 times.
<div className="row align-items-center justify-content-center m-b-10">
<h5>Name goes here</h5>
</div>
This is the type of object I'm dealing with:
Is there a clean way of doing this?
First, it depends on how your data is defined, for example, if the names are in an array, you can create an array of JSX elements that contain each , you can use .map()
Just use:
const x = 5
Array(x).fill().map((el, index) =>
<div className="row align-items-center justify-content-center m-b-10" key={index}>
<h5>Name here</h5>
</div>
)
This is not ideal because you can also iterate over the array of names itself, and get the same result, even cleaner.
<div>
{
arrayOfNames.map((el, index) => (
<div className="row align-items-center justify-content-center m-b-10" key={index}>
<h5>`${el.first_name} ${el.last_name}`</h5>
</div>
))
}
</div>
Assuming you got all of the people names in an array. You can use map over the array when rendering`:
{ yourObject.map((person, idx)=>(
<div className="row align-items-center justify-content-center m-b-10" key={idx}>
<h5>{person.first_name + " " + person.last_name}</h5>
</div>
)}
(Of course, make sure this code is wrapped with another element)
I am trying to put a "col-sm-6" inside a row with checking a condition . But when null value is coming it is returning a blank div with ".col-sm-6" class, I need to hide that class when value is null.
<div className="row">
{attribute.attributeValues.map((list, index) =>
<div className="col-sm-6" >
{list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>:''
}
</div>
)}
</div>
this is giving results like:
like:
<div class="row">
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6"></div>
<div class="col-sm-6"></div>
</div>
But I want:
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6">Some Value</div>
<div class="col-sm-6">Some Value</div>
You can make use of React.Fragment like
<div className="row">
{attribute.attributeValues.map((list, index) =>
<React.Fragment key={index}>
{list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>:''
}
</React.Fragment>
)}
</div>
According to the docs:
A common pattern in React is for a component to return multiple
elements. Fragments let you group a list of children without adding
extra nodes to the DOM.
Second method to remove the wrapping {} in the ternary condition
<div className="row">
{attribute.attributeValues.map((list, index) =>
list.isSelected === 1 ?
<div className="style">
<span><i className="fa fa-check"></i>{list.tag_value}</span>
</div>: null
)}
</div>
Actually, you just need to use filter (MDN documentation) before the map. You can do something like:
attribute.attributeValues.filter(list => list.tag_value).map(...
That way, with filter, you return a new Array in which only items with a "real" list.tag_value value.
In JavaScript, everything without a "Value" is False (JavaScript Booleans). That means that the filter above will filter out any list.tag_value equal to: undefined, null, empty String ("") or Number equal to 0.
I m actually developping an application using fluxible and I m facing a problem using route parameters.
Actually, I m having this render function :
render() {
return (
<div className="card small hoverable">
<div className="card-image">
<img src="http://www.gizmobolt.com/wp-content/uploads/2014/11/14-77.jpg"/>
<span className="card-title">{this.props.title}</span>
</div>
<div className="card-content">
<p>I am a very simple card. I am good at containing small bits of information.
I am convenient because I require little markup to use effectively.</p>
</div>
<div className="card-action">
<NavLink routeName="ProjectDetail" navParams={{id: this.props.key}}>Manage</NavLink>
</div>
</div>
);
}
And this route in my ./conf/routes.js :
ProjectDetail: {
path: '/project/:id/details',
method: 'get',
page: 'ProjectDetail',
title: 'Project detail',
handler: require('../components/ProjectDetail'),
notInMenu:true
}
And here's the error that I get :
/soft/blog/node_modules/fluxible-router/lib/createNavLinkComponent.js:94
throw new Error('NavLink created without href or unresolvable
^
Error: NavLink created without href or unresolvable routeName 'ProjectDetail'
It happens only when I try to use parametered routes in routes.js.
I dont have any idea of making it differently :-/
according to https://github.com/facebook/react/issues/2429 you cannot reference this.key or this.props.key from a component.
The recommendation in this comment is to
I would suggest renaming or duplicating the prop [sic key] name as a possible fix if you really need to access it.
so change your code to something like
render() {
return (
<div className="card small hoverable">
<div className="card-image">
<img src="http://www.gizmobolt.com/wp-content/uploads/2014/11/14-77.jpg"/>
<span className="card-title">{this.props.title}</span>
</div>
<div className="card-content">
<p>I am a very simple card. I am good at containing small bits of information.
I am convenient because I require little markup to use effectively.</p>
</div>
<div className="card-action">
<NavLink routeName="ProjectDetail" navParams={{id: this.props.id}}>Manage</NavLink>
</div>
</div>
);
}
and in the parent rendering component, do:
render() {
{this.states.cards.map(function eachCard(card) {
return <CardItem key={card.id} id={card.id} />;
});
}
It looks like you have the casing wrong: ProjectDetail vs projectDetail. Make sure you are being consistent.