iterate a list inside another in react - javascript

i'm pretty new to react and javascript and i want to know how to iterate a list inside another list.
I have this json variable:
this.state = {
groups: [{
name: '',
permission: [{
name: ''
}]
}]
}
What I want to do is to count the number of elements the second list has, i did this following code but it sends the follwoing error, groups.map is not a function:
render() {
let permissionGroup = this.state.groups.map((groups) => {
let x = 0;
groups.map((permission) => {
x++;
})
})
return (
<div>
{this.state.groups.map((groups) => {
return (<li key={groups.code}>
<Card style={{ width: '20rem' }}>
<Card.Body>
<Card.Title>{groups.name}</Card.Title>
<Card.Subtitle className="mb-2 text- enter code heremuted">Permissions info</Card.Subtitle>
<Card.Text>
This group has {permissionGroup} permissions in it.
</Card.Text>
<Card.Link href="#">Add Permission</Card.Link>
<Card.Link href="#">Remove Permission</Card.Link>
</Card.Body>
</Card>
</li>)
})}
</div>

Inside your first map, it should be groups.permission.map, not groups.map.
let permissionGroup = this.state.groups.map((groups) => {
let x = 0;
groups.permission.map((permission) => {
That's because your first map is defining each "groups" as this:
{name: '', permission: [{name: ''}]}
So groups in this sense is an object, not an array. Access permission to get to the array you want.

Related

Rendering nested data (objects from an array inside an object of another array ) From backend - ReactJS (JSX)

I have JSON data i am trying to render to the front end of my application.
and I am trying to get the name of all the objects inside the betTypes array to the front end as a List. So far, I am only able to query a single object from the nested array.
const data = {
games: [
{
name: 'BlackJack',
slug: 'American Blackjack',
category: 'Card games',
image: '/images/bj.jpg',
betTypes: [
{
name: 'Flush',
det: 'Flush',
category: 'American Blackjack',
description:
'The player’s two initial cards and dealer’s first cards are all of the same suits and have different values (it is also valid if two of the three cards are of the same value)',
image: '',
},
{
name: 'Mixed Color Pair',
det: 'MXP',
category: 'American Blackjack',
description:
'When the player gets two initial cards as a pair (same value) of different colour and different suit.',
image: '',
},
],
},
},
This is what my front-end code looks like
function GameScreen() {
const params = useParams();
const { slug } = params;
const [{ loading, error, game }, dispatch] = useReducer(reducer, {
game: [],
loading: true,
error: '',
});
// const [games, setGames] = useState([]);
useEffect(() => {
const fetchData = async () => {
dispatch({ type: 'FETCH_REQUEST' });
try {
const result = await axios.get(`/api/games/slug/${slug}`);
dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
} catch (err) {
dispatch({ type: 'FETCH_FAIL', payload: err.message });
}
//setGames(result.data);
};
fetchData();
}, [slug]);
return loading ? (
<div>
<LoadingSpin />
</div>
) : error ? (
<div>{error}</div>
) : (
<div>
<Row>
<Col md={12}>
<h1>{game.name}</h1> <hr />
<img className="img-large" src={game.image} alt={game.name} />
</Col>
<Col md={3}>
<ListGroup>
<ListGroup.Item style={{ marginTop: '10px' }}>
<h6>{game.betTypes[3].name}</h6>
</ListGroup.Item>
</ListGroup>
</Col>
<Col md={3}></Col>
</Row>
</div>
);
}
I need help sorting it out please.
<ListGroup>
{game.betTypes.map((item)=>
<ListGroup.Item key={item.name} style={{ marginTop: '10px' }}>
<h6>{item.name}</h6>
</ListGroup.Item>)
}
</ListGroup>

Material UI - Chip Array

I am writing some code for a ReactJS component to have an array of chips. I want each chip to be styled uniquely, so I set up a makeStyles class for each one. I was having trouble trying to figure out how to change the class for each tag. This is what I got so far:
const classes = useStyles();
const [chipData, setChipData] = React.useState([
{ key: 0, label: 'Heating' },
{ key: 1, label: 'Printing' },
{ key: 2, label: 'Resetting' },
{ key: 3, label: 'Idle' },
{ key: 4, label: 'Suspended' },
{ key: 5, label: 'Suspend in Progress' },
{ key: 6, label: 'Attention - Printer Connection Lost' },
{ key: 7, label: 'Attention - Filament Out' },
{ key: 8, label: 'Attention - Cooldown Failed' },
]);
return (
<Box display="flex" flexDirection="row" alignItems="flex-start" className={classes.container}>
{chipData.map((data) => {
return (
<div classes={classes.chipContainer}>
<li key={data.key}>
<Chip
label={data.label}
if (label === 'Heating') {
className={classes.heatingTag}
}
/>
</li>
</div>
);
})}
</Box>
);
}
export default PrinterStatusTags
So within the chip element, I have an if statement that is used to assign a specific class based on the label. My plan was to have an if statement for each label, but I am getting the following error:
Parsing error: Unexpected token
Any ideas how I can assign a class based on the chip?
Updated Answer
I would 2 things:
Add a new type property for every chip.
Create a mapper from the type (in the 1st point) to the classes
const classesMapper = {
first: classes.firstClass,
second: classes.secondClass
// ...
};
const [chipData, setChipData] = React.useState([
{ key: 0, label: 'Heating', type: 'first' },
{ key: 1, label: 'Printing', type: 'seocnd' },
// ....
]);
After you have the mapping between every chip to its type. Just render it:
return (
<Box display="flex" flexDirection="row" alignItems="flex-start" className={classes.container}>
{chipData.map((data) => {
return (
<div classes={classes.chipContainer}>
<li key={data.key}>
<Chip
label={data.label}
className={classesMapper[data.type]} />
</li>
</div>
);
})}
</Box>
);
Old Answer
You should write the code a little bit different:
Use className property and not the property class (nor classes)
Set the condition inside the className property. Please note that there are better ways to set the right class but for your case, that would be good enough.
This is the code as it should be:
<div classeName={classes.chipContainer}>
<li key={data.key}>
<Chip label={data.label} className={ label ==== 'Heating' && classes.heatingTag}/>
</li>
</div>

showing only first element from data

Hi all I have following code: my code
In this scenario I am receiving some data from backend
const attachments = [
{
id: 1,
name: "someURLL_Name_1",
link: "https://someURLL_Name_1",
img: "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg"
},
{
id: 2,
name: "someURLL_Name_2",
link: "https://someURLL_Name_2",
img: "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg"
},
{
id: 3,
name: "someURL_Name_3",
link: "https://someURLL_Name_3",
img: "https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg"
}
];
I need to map them all and show only first element form my data, and show with numbers rest hided data.
In the end it should be like something like this:
someURL_Name_1 https://someURLL_Name_1 +2 more
I successfully mapped all my data and write little logic for + more.
<div className={Styles.attachments}>
{data.map((item) => {
return <Attachment key={item.id} data={item} image={item.img} />;
})}
{data.length > 1 && (
<span className={Styles.more}>+{data.length - 1} more</span>
)}
</div>
Please help me to resolve a problem. Again, I want to show only first element , and then if there are another elements then I should hide them and show hide elements with numbers.
Thanks.
Just don't map over all entries then. The following will work :-
export const Attachments = ({ data }) => {
return (
<div className={Styles.attachments}>
{data[0] && (
<Attachment key={data[0].id} data={data[0]} image={data[0].img} />
)}
{data.length > 1 && (
<span className={Styles.more}>+{data.length - 1} more</span>
)}
</div>
);
};

How to create a dynamic SectionList?

I am trying to build a section list where the list header is the name of a class (like a school class) and the section list is the assignments that are assigned to that class.
This is my section list component:
<SectionList
sections={classData}
keyExtractor={item => item.class.id}
renderSectionHeader={({ section: classProps }) => {
return (
<Text style={styles.textStyle}>{classProps.name}</Text>
);
}}
renderItem={({ item }) => {
return (
<HomeworkItem
homeworkItem={item}
deleteHomework={() => this.props.removeHomework(item)}
/>
);
}}
/>
This is the code to get classData:
const classData = [];
for (let x = 0; x < this.props.classes.length; x++) {
classData.push({
classProps: this.props.classes[x],
assignments: this.filterAssignments(this.props.classes[x], this.props.homework)
});
}
And the filter assignments function is this:
filterAssignments(c, hw) {
return hw.filter(item => item.className === c.name);
}
I am receiving an error that items.length is undefined at the beginning of the list. The data appears to be working. If anyone knows how I can do this correctly your help would be greatly appreciated.
The react native docs state the following format:
const DATA = [
{
title: 'Main dishes',
data: ['Pizza', 'Burger', 'Risotto'],
},
{
title: 'Sides',
data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
}
];
this format can be achieved with the following loop:
const classData = this.props.classes.map(item => ({
title: item.name
data: this.filterAssignments(item, this.props.homework)
}));
the classData can now be passed to <SectionList as such:
<SectionList
sections={classData}

React, update array's total count state when new item is added to it

I have my array where you can add a "player" to it and it updates just fine. I also have a total number of players that looks at the array and gives the total sum. It works but it does not factor in the new items.
I know I need to pass it the new updated state of the array (players) but I'm just stuck on how to do that.
I've provided snips of my code as follows
Array
const players = [
{
name: 'Jabba',
score: 10,
id: 11
},
{
name: 'Han',
id: 1
},
{
name: 'Luke',
id: 2
},
Function to add to the array
handleChange = e => {
this.setState({
newPlayerName: e.target.value
});
};
handleAddPlayer = e => {
this.setState(prevState => ({
players: [
...prevState.players,
{
name: this.state.newPlayerName,
id: getRandomInt(20, 155)
}
]
}));
};
my state
this.state = {
id: players.id,
totalScore: 0,
totalPlayers: players,
countInfo: [],
evilName: '',
color: '#6E68C5',
scoreColor: '#74D8FF',
fontAwe: 'score-icon',
incrementcolor: '',
scoreNameColor: 'white',
glow: '',
buttonStyle: 'count-button-start',
newPlayerName: '',
max_chars: 15,
chars_left: '',
players
};
And finally the function that should update the total but doesn't and where I'm stuck
function Stats(props) {
const totalPlayers = props.players.length;
const totalScore = props.players.reduce(
function(total, player) {
return props.totalScore + props.totalScore;
},
0
);
return (
<div style={{ width: '100%' }}>
<PlayerNumb>Number of players: <b>{totalPlayers}</b></PlayerNumb>
</div>
);
}
the const totalPlayers = props.players.length; is where I seemed to be tripped up. Any help would be greatly appreciated and apologies if I gave any confusing information as React is still new to me.
Also an example of how I called stats:
<Stats
style={{ width: '100%' }}
totalScore={this.state.totalScore}
players={players}
/>
And the complete render code of how Players is created
render() {
const listPlayers = this.state.players.map(player => (
<Counter
key={player.id}
player={player}
playersArray={this.state.players}
name={player.name}
sortableGroupDecorator={this.sortableGroupDecorator}
decrementCountTotal={this.decrementCountTotal}
incrementCountTotal={this.incrementCountTotal}
removePlayer={this.removePlayer.bind(this)} //bind this to stay in the context of the parent component
handleClick={player}
/>
));
return (
<ContainLeft style={{ alignItems: 'center' }}>
<ProjectTitle>Score Keeper</ProjectTitle>
<Copy>
A sortable list of players that with adjustable scores. Warning, don't go negative!
</Copy>
<GroupHolder>
<Stats
style={{ width: '100%' }}
totalScore={this.state.totalScore}
players={players}
/>
<div
style={{ width: '100%' }}
className="container"
ref={this.sortableContainersDecorator}
>
<div className="group">
<div className="group-list" ref={this.sortableGroupDecorator}>
{listPlayers}
</div>
</div>
</div>
<HandleForm>
<form
style={{ width: '100%' }}
onSubmit={this.handleClick.bind(this)}
>
<p className="sort-player">Add A Player</p>
<InputText
type="text"
maxLength="15"
max="4"
name="usr"
placeholder="Enter a new name"
value={this.state.newPlayerName}
onChange={this.handleChange}
/>
<PlayerButton onClick={this.handleAddPlayer}>
Press to Add Player
</PlayerButton>
<CharacterCount>
Characters left
{' '}
{this.state.max_chars - this.state.newPlayerName.length}
</CharacterCount>
</form>
</HandleForm>
</GroupHolder>
</ContainLeft>
);
}
}
export default Container;
You're calling your render function with an undefined variable called players
players={players}
You either need to pass this.state.players or define it with const players = this.state.players;
You should always be developing locally with an eslint plugin for your editor, which will highlight problems like these as syntax errors and save you hours of time.

Categories