I am stuck at mapping value with object.
I have Array of objects
const data = [
{
_id: "535345345345345345311",
name: "Activity",
description: "this is activity",
filters: []
},
{
_id: "535345345345345345311",
name: "Activity",
description: "this is activity",
filters: [
{ _id: "49823476237423984", name: "ACTIVITY filter", origin: "ACTIVITY" }
]
}
];
Here, like that array of object have user_of then it should show User Reading data from the object. Or if data is not present at the object then show as it is. Like if there's data example_of its there in that above array object, but not in object then show example_of only....
{
"user_of": "User",
"student_of": "Student",
"test_of": "TEST"
}
Where this is the object, now if data has user_of I want to show as User in the result output. Similarly if I have student_of in data then I want to show Student
Below is the code where I am trying to achieve this.
{data.filters.map((filter, index) => (
<>
{index < 2 && (
<span style={{ textTransform: "capitalize" }}>
{filter.origin.toLowerCase()}
{index === 0 && record.filters.length > 1 && <span>, </span>}
</span>
)}
</>
))}
{data.filters.length > 2 && (
<span> +{record.filters.length - 2} </span>
)}
also Here's working example of the code https://codesandbox.io/s/hardcore-kilby-hhbon?file=/index.js
What I am getting currently is below
And here's what I expect is
Basically all I want is replace the value with that object value(for naming convention purpose). You can see this on codesandbox link above, I am confused. (New to JS world, Previously with python)
Can someone help me?
You're pretty close:
...
<>
{index < 2 && (
<span style={{ textTransform: "capitalize" }}>
{objet[filter.origin]}
{index === 0 && record.filters.length > 1 && <span>, </span>}
</span>
)}
</>
...
I just changed this to return {objet[filter.origin]}
objet is already defined but you need to add activity_of
const objet = {
user_of: "User",
student_of: "Student",
test_of: "TEST",
activity_of: "Activity"
};
Related
this is what the data shows inside the console:
I tried displaying it with these but it failed
{Object.entries(value).map(([key, value]) => {
return (
<p key={key}>
<li>
{key}
{value}
{console.log(value.id)} //this will show as undefined
</li>
</p>
);
})}
{value} will show this error :
Objects are not valid as a React child (found: object with keys {color, quantity}). If you meant to render a collection of children, use an array instead.
{value.id} or the {value.name} will show as undefined
With the map, it will say that value.map is not a function
{value.map((value, key) => (
<>
<div>{value.id}</div>
<div>{value.name}</div>
</>
))}
codesandbox: https://codesandbox.io/s/display-the-manipulated-data-dy204r
Your object has a complex structure, and in order to iterate, you need to check if one of the items is Array using Array.isArray(), if yes, then loop them and use, else use the properties directly
Below is the working code of the mock of your object and iteration. I have just logged the values, you can use them in any way you want
let myObj = {
s: [{
color: 'a',
q: '8'
}, {
color: 'b',
q: '2'
}],
name: 'Anne',
id : 18
}
Object.keys(myObj).forEach(function(key) {
if (Array.isArray(myObj[key])) {
myObj[key].forEach(function (item, index) {
console.log(item.color);
console.log(item.q);
});
}
else
console.log(myObj[key])
});
You can do something like this
{Object.entries(value).map((v, key) => {
return (
<p key={key}>
<li>
{key}
{v.name}
{console.log(v.id)} //this will show as undefined
</li>
</p>
);
})}
I have an array with several objects. Inside each object i have a field called type that can be either a or b. I am trying to conditional render a specific view for type a and a specific view for type b.
Here is my array:
DATA=[
{id:1, type:'a'},{id:2,type:'b'}
]
return(
{DATA.type === 'a' ?
<Text>I am type A</Text>
:
<Text>I am Type B </Text>
}
)
When i do that nothing appears on the screen.
UPDATE
DATA=[
{id:1, type:'a',locked:true},
{id:2,type:'b',locked:false}
]
const[isLocked,setIsLocked]=useState(false)
return(
{isLocked && DATA.map((item) => item.type === 'a')) ?
<Text>I am type A</Text>
:
null}
)
it is still not working. I am type A still appears on all pages of my carousel.
You need to map your array to accomplish it. Otherwise, you can't get the correct key.
DATA = [
{ id:1, type:a },
{ id:2, type:b },
]
return(
DATA.map((item) => item.type === 'a'
? <Text>I am type A</Text>
: <Text>I am Type B </Text>
))
I have a JSON of team members:
[
{
"name": "Allie Armstrong",
"title": "Head of Finance",
"teams": ["Finance", "Europe"]
},
....]
I map over it, it's fine.
{teamMembersList.map(teamMember => {
return(
<TeamMember
teamMembers={teamMember}
/>
)
})}
But the teams part comes together.
I would like to basically get teammember.teams[0], then teammember.teams[1] etc, so they can be in their own span. Instead of having them as FinanceEurope
The number of elements in this array varies.
TRY :
{ if(teamMembersList.teams && teamMembersList.teams.length) {
teamMembersList.teams.map(teamMember => {
return( <TeamMember teamMembers={teamMember} />)
})
} else {
return('')
}
}
Also you need to check if teamMembersList.teams have some value because if it returns undefined / null OR string then it will not work and will give you error.
In the end I moved my JSON data into the js file as a const.
Then:
{teamMembersList.map(x => {
return x.teams.map(teams => (
<li key={x.id}>
{teams}
</li>
))
})}
It works fine :)
https://codesandbox.io/s/r546o8v0kq
My above sandbox shows basic mapping of an array of items. This forms a list of notes, dates and an icon depending on what type of item it is.
I am working some logic that maps each item to find out what value it is, based on that I assign the value a string to complete the type of font awesome logo.
const noteType = _.uniq(notes.map(value => value.intelType));
const noteIcon = [
`${noteType}`.toUpperCase() == "EDUCATION"
? "paper-plane"
: `${noteType}`.toUpperCase() == "ELIGIBILITY"
? "heart"
: `${noteType}`.toUpperCase() == "GENERAL"
? "twitter"
: null
];
If "intelType" has a value of "education" it would return the "paper-plane" string to complete the icon. e.g fa fa-${noteIcon}
<List>
{notes.map((note, index) =>
note !== "" ? (
<React.Fragment>
<ListItem className="pl-0">
<i class={`fa fa-${noteIcon}`} aria-hidden="true" />
<ListItemText
secondary={moment(note.createdAt).format("DD-MMM-YYYY")}
/>
</ListItem>
<p>{note.note}</p>
<Divider />
</React.Fragment>
) : null
)}
</List>
Its not getting mapped and returning all three values, which does not meet any criteria therefore returns null as requested. I'm a bit stuck as what to do next here.
You can define an object that maps intel type to icon names:
const noteIconMap =
{ "EDUCATION": "paper-plane",
"ELIGIBILITY": "heart",
"GENERAL": "twitter",
};
And look it up this way inside the render:
<i class={`fa fa-${noteIconMap[note.intelType.toUpperCase()]}`} aria-hidden="true" />
Although, beware, if there is a case where note can have intelType undefined, toUpperCase call will throw an error.
Here's a link to working modified sandbox:
https://codesandbox.io/s/ojz2lzz03z
I'm not sure what's going on with this bit of code:
const noteIcon = [
`${noteType}`.toUpperCase() == "EDUCATION"
? "paper-plane"
: `${noteType}`.toUpperCase() == "ELIGIBILITY"
? "heart"
: `${noteType}`.toUpperCase() == "GENERAL"
? "twitter"
: null
]
But it makes more sense to me to store that information as an object and then access the icon type that way.
const icons = {
EDUCATION: 'paper-plane',
ELIGIBILITY: 'heart',
GENERAL: 'twitter'
}
And then going:
icons[noteType]
You need to get an icon in the map for each note.intelType. Since you're passing an array of ids, none of the icons is matched, and the result is always null.
A simple solution is to create a Map of types to icons (iconsMap), and get the icon from the Map using note.intelType.
btw - currently note.intelType us always uppercase, so you don't need to transform it.
sandbox
const iconsMap = new Map([
['EDUCATION', 'paper-plane'],
['ELIGIBILITY', 'heart'],
['GENERAL', 'twitter'],
]);
class Notes extends Component {
constructor(props) {
super(props);
this.state = {};
}
render() {
const { notes, classes } = this.props;
return (
<React.Fragment>
<List>
{notes.map((note, index) =>
note !== "" ? (
<React.Fragment>
<ListItem className="pl-0">
<i class={`fa fa-${iconsMap.get(note.intelType)}`} aria-hidden="true" />
<ListItemText
secondary={moment(note.createdAt).format("DD-MMM-YYYY")}
/>
</ListItem>
<p>{note.note}</p>
<Divider />
</React.Fragment>
) : null
)}
</List>
</React.Fragment>
);
}
}
I have a problem with this code:
<InfiniteScroll
dataLength={beers.length}
next={fetchMoreBeers}
hasMore={true}
loader={<p>Loading ...</p>}
endMessage={<p id="beers-end">No more beers :(</p>}
>
{beers.map((beer, index) => (
<div key={index}>
<Link
to={{
pathname: `/beer/${beer.id}`,
state: { beer: beer.id },
}}
>
<div className="beer-wrapper">
<div className="beer">
<img
className="beer-img"
src={beer.image_url}
alt={beer.name}
/>
<p className="beer-name">
{beer.name.length < 15
? `${beer.name}`
: `${beer.name.substring(0, 20)}...`}
</p>
<p className="beer-tagline">
{beer.tagline.length < 20
? `${beer.tagline}`
: `${beer.tagline.substring(0, 25)}...`}
</p>
</div>
</div>
</Link>
<Route path="/beer/:id" component={Beer} />
</div>
))}
</InfiniteScroll>;
And when the page is scrolled the error occurs:
"TypeError: Cannot read property 'id' of undefined"
for this line:
pathname: `/beer/${beer.id}`,
This seems like InfiniteScroll doesn't see the data from map() function ....
Maybe some of you know how to fix this problem?
Thanks for any tips!
Perhaps the issue is with template literals. When we add template literals directly it throws such issues. I experienced the same in my projects.
May be you can try in below way
render(){
const { beers } = this.props;
const beerItems = beers.map((beer, index) => {
let pathName = `/beer/${beer.id}`;
return (
<div key={index}>
<Link to={{
pathname: {pathName},
state: {"beer": beer.id}
}} >
<div className="beer-wrapper">
<div className="beer">
<img className="beer-img" src={beer.image_url} alt={beer.name} />
<p className="beer-name">
{beer.name.length < 15 ? beer.name : beer.name.substring(0, 20) }
</p>
<p className="beer-tagline">
{beer.tagline.length < 20 ? beer.tagline : beer.tagline.substring(0, 25) }
</p>
</div>
</div>
</Link>
<Route path="/beer/:id" component={Beer} />
</div>
)
}
return(
<InfiniteScroll
dataLength={beers.length}
next={fetchMoreBeers}
hasMore={true}
loader={<p>Loading ...</p>}
endMessage={<p id="beers-end">No more beers :(</p>}
>
{beerItems}
</InfiniteScroll>
)
}
Maybe there is an undefined value stored in beers array. Try to filter them out, like so:
beers.filter(Boolean).map((beer, index) => (
// ...
)
Also, I've noticed that hasMore prop is always set to true. To see if it helps, try something like:
<InfiniteScroll
dataLength={beers.length}
next={fetchMoreBeers}
hasMore={beers.length < 25} // or hasMore={this.state.hasMore}
loader={<p>Loading ...</p>}
endMessage={<p id="beers-end">No more beers :(</p>}
> ...
EDIT:
You are using Array.from({ length: 20 })). The output array will contain 20 undefined values. That is why you should consider beers.filter(Boolean).
I suppose this is what you really meant:
this.setState({
items: this.state.beers.concat(Array.from(this.state.beers))
})
or:
this.setState({
items: [...this.state.beers, ...this.state.beers]
})
You should check for the status code when fetching the beers. fetch will still let you do your thing even if the request failed. If you exceed your endpoint data limit, you'll get this data added to your beer array:
{
"statusCode": 400,
"error": "Bad Request",
"message": "Invalid query params",
"data": [{
"param": "per_page",
"msg": "Must be a number greater than 0 and less than 80",
"value": "100"
}]
}
As you can see there's no id param there which makes this strange error to show up.
Including a json schema validator (like https://ajv.js.org/) to make sure the data is in expected format would be a perfect choice.
I think that this problem is because of data records limitations in this Api .