I am looping over the people array and getting the first array. My screen should say "person 1". but it is blank and
nothing is being returned.
const people = [
[
{
name: 'person 1'
}
],
[
{
name: 'person 2'
}
],
]
export default function Index() {
return (
<>
{people.slice(0,1).map((person) => {
return <h1>{person.name}</h1>
})}
</>
)
}
the code works when i do this, but I need to use slice
export default function Index() {
return (
<>
{people[0].map((person) => {
return <h1>{person.name}</h1>
})}
</>
)
}
people.slice(0, 1), unlike you'd expect, returns [[{ name: "person 1" }]], not [{ name: "person 1" }] (Array#slice returns a "slice" of an array, and in your special case it's an array with a single value, but not the single value itself). You'll have to access the inner array to get what you want:
// in your JSX
people.slice(0, 1).map(([person]) => (
<h1>{person.name}</h1>
))
Notice that the argument destructures the input array (this assumes each value in people is an array with exactly one element; if not, loop over that content).
Another option would be to Array#flatMap to "un-nest" those values:
// in your JSX
people.slice(0, 1).flatMap(person => (
<h1>{person.name}</h1>
))
This will work:
return (
<>
{people.slice(0,1).map((person) => {
return <h1>{person[0].name}</h1>
})}
</>
)
Because each person is still an array, you can't access the object's properties directly without first accessing the array that wraps it.
You have to modify the data structor of people.
const people = [
{
name: 'person 1'
},
{
name: 'person 2'
}
];
In you case, person in map method is Array type. So, person.name's value will be undefined.
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 am working on a NextJs project with a Firebase Store.
I access a collection and get an array with objects with a random key and as value the data:
const data = [
{
randomdocid67233: {
name: "ABC",
latinName: "DEF"
}
},
{
randomdocid6d7dddd233: {
name: "GHI",
latinName: "JKI"
}
}
];
Beause I dont know the randomdocid's I cant figure out how to display the name and latinName. I have made a codesandbox with the problem to illustrate it: https://codesandbox.io/s/spring-fast-w0tt4?file=/src/App.js:56-268
Im sure it's actually easy to do but I don't seem to be able to figure it out. Hopefully someone knows!
Thanks,
Santi.
You can use Object.keys() as solution here
{data.map((item, index)=> {
let key=Object.keys(item)[0]
return <div key={key}> // better to use unique key value then index
{item[key].latinName}
</div>
)}
You need to first get the key inside every object and return the value of that key in the map. Update the code based on your need to render the data after you fetch it. You can do it like this
export default function App() {
const data = [
{
randomdocid67233: {
name: "ABC",
latinName: "DEF"
}
},
{
randomdocid67233: {
name: "GHI",
latinName: "JKI"
}
}
];
const newData = data.map(item => {
const key = Object.keys(item)[0];
return item[key]
})
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
{newData.map((item, index) => (
<div key={index}>
{item.name} {item.latinName}
</div>
))}
</div>
);
}
I'm getting undefined when accessing element of array but console showed value when using the array name only.
The code:
const Part = (props) => {
return <p>{props.name} {props.exercises}</p>
}
const Content = (props) => {
// when i use console.log(props[0])
// it shows undefined
//
// but when i use console.log(props)
// it shows the array information as
// {parts: Array(3)}
// parts: Array(3)
// 0: {name: 'Fundamentals of React', exercises: 10}
// 1: {name: 'Using props to pass data', exercises: 7}
// 2: {name: 'State of a component', exercises: 14}
// length: 3
// [[Prototype]]: Array(0)
// [[Prototype]]: Object
return (
<div>
<Part parts={props[0]} />
</div>
)
}
const App = () => {
const course = 'Half Stack application development'
const parts = [
{
name: 'Fundamentals of React',
exercises: 10
},
{
name: 'Using props to pass data',
exercises: 7
},
{
name: 'State of a component',
exercises: 14
}
]
return (
<div>
<Content parts={parts} />
</div>
)
}
So I don't understand why in Content, console.log(props) returns array info but console.log(props[0])says undefined, which gets nothing in App.
Update:
Thanks for everyone's reply. Now I know if I use 'props.parts' inside Content, I will get the right result. Then I got another question (Sorry I'm new to JS and React) :
Because 'parts' is defined in App and passed to Content. I shouldn't use or know 'parts' when defining Content. So why do I need to use 'props.parts' inside Content?
// when i use console.log(props[0])
// it shows undefined
because the array variable name is parts as you have mentioned here:
// but when i use console.log(props)
// it shows the array information as
// {parts: Array(3)}
// parts: Array(3)
So try this:
console.log(props.parts)
or
console.log(props.parts[0])
console.log(props) not return array, it return object has 1 attribute name parts(parts is array)
=> Solution:
const Content = props => {
const { parts } = props;
return (
<div>
<Part parts=parts[0] />
</div>
)
}
I have an array that I am passing down to a child component, where I want all the array elements to render in a list. Not complicated, I've done this a bunch of times, except this time I'm not able to get it to format the way I want.
In my parent, I am filtering through an array of objects in my state, and returning the object that I want:
state = {
activeTab: 0,
tabs: [
{
id: 0,
icon: <AiFillShopping />,
label: 'Groceries',
content: ['grocery list', 'test']
},
{
id: 1,
icon: <FaSchool />,
label: 'School',
content: ['school list', 'test']
}
],
value: '',
}
let filteredContent = this.state.tabs.filter((tab, index) => {
if(index === this.state.activeTab) {
return tab;
}
})
console.log(filteredContent) // logs {id: 0, label: "Groceries", content: Array(2)}
Then I'm passing filteredContent to my child, and then in my child I am mapping through the prop to get the content and list the items out as a list:
<ul>
{this.props.content.map(content=> <li>{content.content}</li>)}
</ul>
But it's coming out as one list item, with the elements all in one line like this:
"grocery listtest"
I'm sure I just did something stupid, but I've been staring at it for long at this point I could use another pair of eyes.
Since the content.content is an array of renderable content, i.e. strings, it is concatenated for you by React and rendered.
You will want to flatten the nested content arrays first, then map them to JSX.
<ul>
{content
.flatMap((content) => content.content)
.map((content) => (
<li key={content}>{content}</li>
))}
</ul>
function App() {
const content = [
{
id: 0,
// icon: <AiFillShopping />,
label: "Groceries",
content: ["grocery list", "test"]
},
{
id: 1,
// icon: <FaSchool />,
label: "School",
content: ["school list", "test"]
}
];
return (
<div className="App">
<ul>
{content
.flatMap((content) => content.content)
.map((content) => (
<li key={content}>{content}</li>
))}
</ul>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(
<App />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root" />
If you happen to just want a comma separated content list they join the content array.
<ul>
{content.map((content) => (
<li key={content}>{content.content.join(", ")}</li>
))}
</ul>
Note on filtering
Array.prototype.filter callback returns a boolean, not the element you want in the result array. Your filter code only works by "accident" since returning a tab is coerced to a truthy value, and when the index doesn't match you are implicitly returning undefined which is a falsey value. You should just return the result of the condition.
const filteredContent = this.state.tabs.filter(
(tab, index) => index === this.state.activeTab
);
Since you are filtering the tabs array and (presumably) rendering them then you might not want to use the array index as it isn't intrinsically related to any tab. Using the tab.id and storing an active tab id would a better choice since the id isn't related to any relative position in the array it'll always be the same per tab object.
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 :)