I have a simple state:
const INITIAL_PEOPLE = {
name: 'Friends',
list: [
{
id: 1,
name: 'Alexander',
child: [
{
id: 2,
name: 'Romuald'
},
{
id: 3,
name: 'Vanessa'
}
]
},
{
id: 4,
name: 'Alex',
child: [
{
id: 5,
name: 'Jessica'
}
]
}
]
}
Now I want to print that. Look at my code
{prople.list.map(person =>
<li key={person.id}>{person.name}
{person.child.map(child =>
{child.name}
)}
</li>
)}
First loop works correctly but if I added second loop (child), console catch an error that person.child is undefined. Why it doesn't work?
You were not returning any value from your map function.
{INITIAL_PEOPLE.list.map((person) => {
return (
<li key={person.id}>
{person.name}
{person.child.map((child) => {
return child.name;
})}
</li>
);
})}
Your code should be written like this with a check if person have a child array.
{prople.list.map(person =>
<li key={person.id}>{person.name}
{person.child && person.child.length && person.child.map(child =>
{return child.name }
)}
</li>
)}
Here before calling the map function for child, we are checking if person has an attribute named child and if child is an array by checking if child has a property length by person.child.length. Notice the return part in the nested map.
Related
I am trying to update the state of something on a click from a component by lifting up the state and passing it as a prop into the other component and trying to update it.
this is the App.js
function App() {
const [currentConfig, setCurrentConfig] = useState(0);
const availableConfigs = [
{ id: 1, name: "Config 1", number: 1, key: 1 },
{ id: 2, name: "Config 2", number: 2, key: 2 },
{ id: 3, name: "Config 3", key: 3 },
{ id: 4, name: "Config 4", key: 4 },
{ id: 5, name: "Config 5", key: 5 },
{ id: 6, name: "Config 6", key: 6 },
{ id: 7, name: "Config 7", key: 7 },
];
const [configs, setConfigs] = useState(availableConfigs);
//function undoConfigAnimation(currentConfig) {}
return (
<div>
<Tree
configs={configs}
animateConfigs={startConfigAnimation}
setConfig={setCurrentConfig}
currentConfig={currentConfig}
/>
<NavBar />
</div>
);
function startConfigAnimation(configClicked) {
console.log(currentConfig);
configs.forEach((config) => {
if (configClicked !== config.name) {
var elm = document.getElementById(config.name);
elm.style.transform = "translate(-200px)";
setTimeout(() => (elm.style.transform = "rotateZ(180deg)"), 1000);
}
});
}
}
export default App;
this is the component
function Tree(props) {
return (
<div class="treeContainer">
{props.configs.map((config) => {
return (
<div
id={config.name}
class="container1"
onClick={() => {
props.setConfig(config.name);
props.animateConfigs(config.name);
if (props.currentConfig !== config.name) {
props.setConfig.bind(config.name);
}
}}
>
<Configs configNumber={config.number} configName={config.name} />
</div>
);
})}
</div>
);
}
export default Tree;
currently, it does update the state, but it only updates it to the state before the click so an example output if the currentConfig === 0 would be as follows
click config 1
currentConfig = 0
click config 2
currentConfig = "config 1"
Since the setState is async, the console.log will always be one behind. This does not mean that the state is not updated, but only not displayed in the console or yet available in the function.
So the flow would be:
You dispatch the change.
You call startConfigAnimation, but it is still in sync, so that currentConfig is still the previous value.
The state is updated with the new value.
There are 2 ways to fix this:
Use a useEffect:
Listen to the currentConfig with a useEffect and trigger the animation, if the config changes.
React.useEffect(() => startConfigAnimation(currentConfig), [currentConfig])
You are already passing the new/updated config to startConfigAnimation so you could be using that.
In my React project, I'm passing in an array of objects and wondering how I can set default parameter for the nested array. I've already set it on the main array const Nav = ({ navItems = [] }) but couldn't figure out how to set for nested array. Logically, I tried const Nav = ({ navItems = [], navItems.subMenu = [] }) however seems like syntax is incorrect.
JSX:
const Nav = ({ navItems = [] }) => {
const subItems = navItems.map(el => el.subMenu)
return (
{navItems.map(item => (
<li>
{item.label}
<ul>
{subItems[0].map(subItem => (
<li>{subItem.item}</li>
))}
</ul>
</li>
))}
)
}
Props getting passed in:
<Nav
navItems={[
{
label: "About",
subMenu: [
{
id: 1,
item: "About Sub Item 1",
},
{
id: 2,
item: "About Sub Item 2",
},
{
id: 3,
item: "About Sub Item 3",
},
],
},
{
label: "Blog",
subMenu: [
{
id: 1,
item: "Blog Sub Item 1",
},
{
id: 2,
item: "Blog Sub Item 2",
},
{
id: 3,
item: "Blog Sub Item 3",
},
],
},
]}
/>
Here you go :
const Nav = ({ navItems = [{subMenu : []}] })
// I think you also need to set for label also, else will throw error while render
const Nav = ({ navItems = [{ label: "Default label" ,subMenu : []}] })
Suggestion , you can change the code block to something like this :
const Nav = ({ navItems = [] }) => {
// there is no need of below line
// const subItems = navItems.map(el => el.subMenu)
return (
{navItems.map((item) => (
<li>
{item.label}
<ul>
{item.subMenu.map(subItem => ( //<---- you can use it like this
<li>{subItem.item}</li>
))}
</ul>
</li>
))}
)
}
I think the issue might be that it can't deconstruct the array you're passing. If you do ({obj}), it's being deconstructed and it accesses its properties. If it can't be deconstructed, it fires up an error.
It should work like this
const Nav = ( navItems = [] ) => {
const subItems = navItems.map(el => el.subMenu)
return (
{navItems.map(item => (
<li>
{item.label}
<ul>
{subItems[0].map(subItem => (
<li>{subItem.item}</li>
))}
</ul>
</li>
))}
)
}
Hi I have this list array of object in react js and I don't know how to display in my render view. Anyone can give an idea on how to do it?
Post:{
Store1: [
0:{Id:"0001", Business:"Ministop"}
]
Store2: [{
0:{Id:"0002", Business:"Grocery Store"}
}]
Store3: [
0:{Id:"0003", Business:"Seven Eleven"}
]
Store4: [
0:{Id:"0004", Business:"Big Store"},
1:{Id:"0005", Business:"Medium Store"}
]
}
This is the sample output:
**Store 1**
**Id Business**
0001 Ministop
**Store 2**
**Id Business**
0002 Grocery Store
**Store 3**
**Id Business**
0003 Seven Eleven
**Store 4**
**Id Business**
0004 Big Store
0005 Medium Store
I have this code and I've got an error this.state.post.map is not a function
render() {
const groupList = this.state.post.map((data, index) => {
return (
<div key={index}>
<div>{data}</div>
</div>
)
});
return (
<div>{groupList}</div>
)
}
Thank you
This is how you map it. just change post with this.state.post
const post = {
Store1: [
{ Id: '0001', Business: 'Ministop' }
],
Store2: [
{ Id: '0002', Business: 'Grocery Store' }
],
Store3: [
{ Id: '0003', Business: 'Seven Eleven' }
],
Store4: [
{ Id: '0004', Business: 'Big Store' },
{ Id: '0005', Business: 'Medium Store' }
]
};
console.log(Object.keys(post).reduce((acccumilator, iterator) => {
return [...acccumilator, ...post[iterator]];
}, []));
/*
Object.keys(this.state.post).reduce((acccumilator, iterator) => {
return [...acccumilator, ...post[iterator]];
}, []).map(data => {
return (
<div key={data.id}>
<div>{data.Business}</div>
</div>
)
})
*/
map is not a method of an object. You can map over its keys using Object.keys.
render() {
const groupList = Object.keys(this.state.post).map((key) => {
return (
<div key={key}>
<div>{this.state.post[key]}</div>
</div>
)
});
return (
<div>{groupList}</div>
)
}
However, there are other problems once you fix that but you should try to solve them yourself and ask other questions if you can't
I'm using React and I have the following data structure:
[
{
key: 'test'
data: [
{
id: 1,
name: 'test name',
desc: 'aaaaaaaaa'
},
{
id: 2,
name: 'test name2',
desc: 'aaaaaaaaa'
},
{
id: 3,
name: 'test name3',
desc: 'aaaaaaaaa'
}
]
},
{
key: 'test2'
data: [
{
id: 5,
name: 'test name5',
desc: 'aaaaaaaaa'
},
{
id: 5,
name: 'test name2',
desc: 'aaaaaaaaa'
},
{
id: 6,
name: 'test name6',
desc: 'aaaaaaaaa'
}
]
}
]
I'm looking for a better way of fetching data from such a structure. The thing is that is should be one ul list with li items inside.
I have such a structure for this:
<div className='wrapper'}>
{tabInfo.map(({key, data}) => {
return (
<div className='tab-list' key={key}>
<h4>{key}</h4>
<ul>
{data.map(({id, name, desc}) => {
return (
<li key={id}>
<span className='name'>
{name}
</span>
<span className="desc">{desc}</span>
</li>
)
})}
</ul>
</div>
)
})}
</div>
What is the better way of fetching the data in such a case? I think map inside map isn't good idea.
I believe this will do it, though I haven't tested this to be sure. You can move this to a separate component which can then be used as part of the map:
const ListItem = ({ id, name, desc }) => (
<li key={id}>
<span className='name'>
{name}
</span>
<span className="desc">
{desc}
</span>
</li>
);
<div className='wrapper'}>
{tabInfo.map(({key, data}) => {
return (
<div className='tab-list' key={key}>
<h4>{key}</h4>
<ul>
{data.map(dataItem => <ListItem {...dataItem} />)}
</ul>
</div>
)
})}
</div>
I may have missed something here, so if there are any problems, I'd be happy to know about the,m so I can fix this up
First of all i am very new to React JS. So that i am writing this question. I am trying this for three days.
What I have to do, make a list of category, like-
Category1
->Sub-Category1
->Sub-Category2
Categroy2
Category3
.
.
.
CategoryN
And I have this json data to make the listing
[
{
Id: 1,
Name: "Category1",
ParentId: 0,
},
{
Id: 5,
Name: "Sub-Category1",
ParentId: 1,
},
{
Id: 23,
Name: "Sub-Category2",
ParentId: 1,
},
{
Id: 50,
Name: "Category2",
ParentId: 0,
},
{
Id: 54,
Name: "Category3",
ParentId: 0,
},
];
I have tried many open source examples, but their json data format is not like mine. so that that are not useful for me. I have build something but that is not like my expected result. Here is my jsfiddle link what i have done.
https://jsfiddle.net/mrahman_cse/6wwan1fn/
Note: Every subcategory will goes under a category depend on "ParentId",If any one have "ParentId":0 then, it is actually a category, not subcategory. please see the JSON
Thanks in advance.
You can use this code jsfiddle
This example allows to add new nested categories, and do nested searching.
code with comments:
var SearchExample = React.createClass({
getInitialState: function() {
return {
searchString: ''
};
},
handleChange: function(e) {
this.setState({
searchString: e.target.value.trim().toLowerCase()
});
},
isMatch(e,searchString){
return e.Name.toLowerCase().match(searchString)
},
nestingSerch(e,searchString){
//recursive searching nesting
return this.isMatch(e,searchString) || (e.subcats.length && e.subcats.some(e=>this.nestingSerch(e,searchString)));
},
renderCat(cat){
//recursive rendering
return (
<li key={cat.Id}> {cat.Name}
{(cat.subcats && cat.subcats.length) ? <ul>{cat.subcats.map(this.renderCat)}</ul>:""}
</li>);
},
render() {
let {items} = this.props;
let {searchString} = this.state;
//filtering cattegories
if (searchString.length) {
items = items.filter(e=>this.nestingSerch(e,searchString))
console.log(items);
};
//nesting, adding to cattegories their subcatigories
items.forEach(e=>e.subcats=items.filter(el=>el.ParentId==e.Id));
//filter root categories
items=items.filter(e=>e.ParentId==0);
//filter root categories
return (
<div>
<input onChange={this.handleChange} placeholder="Type here" type="text" value={this.state.searchString}/>
<ul>{items.map(this.renderCat)}</ul>
</div>
);
}
});