Implement Reactjs CRUD Application without unique ID for items - reactjs

I am creating a CRUD application using Reactjs but i'm having a hard time implementing the DELETE feature. I used the key={item + 1} to generate a unique ID for every stored item in the array but I don't really know how to assess it. Here's my code...
the LIST
<ul>
{this.state.items.map(item => (
<li key={item + 1}>
{item}
<button>edit</button>
<button onClick={this.handleDelete}>delete</button>
</li>
))}
</ul>;
delete function
handleDelete(id) {
let items = this.state.items;
this.setState({
items: this.state.items.filter(item => items.id !== id),
});
}
state
this.state = {
input: '',
items: [],
};

you can pas some info to handleDelete
handleDelete(id){
let items = this.state.items.filter(item => items.id !== id);
this.setState({
items: items
});
}
<ul>
{
this.state.items.map(item => (
<li key={item.id}>
{item}
<button>edit</button>
{/* here I send id of current item */}
<button onClick={()=>this.handleDelete(item.id)}>delete</button>
</li>
))}
</ul>
Update. Ignoring id you can use key => index
handleDelete(key){
let items = this.state.items.filter((item, mapKey) => key !== mapKey);
this.setState({
items: items
});
}
<ul>
{
this.state.items.map((item, key) => (
<li key={key}>
{item}
<button>edit</button>
{/* here I send id of current item */}
<button onClick={()=>this.handleDelete(key)}>delete</button>
</li>
))}
</ul>

Related

How to map an array that is inside another in react

I am having trouble with array mappings. There is an array with data I would like to bind to my component. It looks like the following:
export var arrayObjects: IObjects[] = [
{
name: 'First Object',
icon: 'bi bi-capsule',
subMenu: [
{
name: 'First Sub Object',
path: ''
},
{
name: 'Second Sub Object',
path: ''
}
]
}
]
The array's type is an interface IObjects which contais name, icon, path and subMenu: IObjects. I need to access the subMenu items in order to create a dynamic menu. Althought, everytime I try to map and call the objects there is no return.
Below you'll be able to see how the mapping I made goes:
<ul>
{ arrayNavCadastros.map((item:any, subMenu: any) =>(
<li className="nav-item">
<i className={item.icon}></i>
{item.name}
<ul>
{ subMenu.map((name:any) =>(
{name}
))}
</ul>
</li>
)) }
</ul>
I also tried doing something like {item.subMenu.name} but there is also no return.
I'm new to react but I'm used to do these kind of bindings in Angular, which seems way easier since you should only do a loop inside the other subMenu from the arrayObjects... I would appreaciate any help!
Note: when I map the first properties of the arrayObjects (which, from the example, returns 'First Object') it works as well as all the titles for the sub menus.
so you have array in subMenu and in each iterate you have object of element
so you need to change this :
{ subMenu.map((name:any) =>(
{name}
))}
to this :
{ subMenu.map((sub:any) =>(
{sub.name}
))}
Few pointers
provide a key for items in the array
<ul>
{ arrayNavCadastros.map((item:any, subMenu: any) =>(
<li
key={item.id} // key for React to know which item to udpate, when array updated
className="nav-item"
>
<i className={item.icon}></i>
{item.name}
<ul>
{ subMenu.map((item:any, idx: number) =>(
<li key={idx}> // key and might need li
<a href={item.path}>{item.name}</a>
</li>
))}
</ul>
</li>
)) }
</ul>
or you can create a child component
<ul>
{ arrayNavCadastros.map((item:any, subMenu: any) =>(
<li
key={item.id} // key for React to know which item to udpate, when array updated
className="nav-item"
>
<i className={item.icon}></i>
{item.name}
<SubMenu items={subMenu} />
</li>
)) }
</ul>
//child component
const SubMenu = ({ items = []}) => {
return (
<ul>
{ subMenu.map((item:any, idx: number) =>(
<li key={idx}> // key and might need li
<a href={item.path}>{item.name}</a>
</li>
))}
</ul>
)
}
New React documentation has helpful information on working with array
Hope it helps

How can I add an active class when a button is clicked in ReactJS

What i want to acheive is to have an active class when a link is clicked. I'm using react
This is the pagination.js file where I want to have the active class on each number clicked
const Pagination = ({ recordsPerPage, totalRecords, paginate }) => {
const pageNumbers = []
for(let i = 1; i <= Math.ceil(totalRecords / recordsPerPage); i++) {
pageNumbers.push(i)
}
return (
<ul className='pagination center'>
<li class="disabled"><i class="material-icons">chevron_left</i></li>
{pageNumbers.map(number => (
<li key={number} style={{ marginLeft: '5px'}}>
<a href='#!' className='hoverable' onClick={() => paginate(number)}>
{number}
</a>
</li>
))}
<li class="waves-effect"><i class="material-icons">chevron_right</i></li>
</ul>
)
}
You can just add a state here, when your onclick fire, set the state of current index
const Pagination = ({ recordsPerPage, totalRecords, paginate }) => {
const [activePage, setActivePage] = useState(0);
const pageNumbers = []
for(let i = 1; i <= Math.ceil(totalRecords / recordsPerPage); i++) {
pageNumbers.push(i)
}
const handlePaginate = (index) => {
setActivePage(index);
paginate(index)
}
return (
<ul className='pagination center'>
<li class="disabled"><i class="material-icons">chevron_left</i></li>
{pageNumbers.map(number => (
<li key={number} style={{ marginLeft: '5px'}} className={activePage === number && 'active'}>
<a href='#!' className='hoverable' onClick={() => handlePaginate(number)}>
{number}
</a>
</li>
))}
<li class="waves-effect"><i class="material-icons">chevron_right</i></li>
</ul>
)
}
As for initial state, right now just default to 0, but it should be whatever current page you are on.

can't use the Refs properly in react js, Cannot read property of undefined

I am very new to react and js,
I have a menu and submenu, I use a list to map data,
I want to write a function, so onmouseover one item in the list,
if it has submenu, it will show.
the problem is that I can't select the submenu using ref.
It is just too complicated for me, any help would be much appreciated!
enter image description here
import React, { Component } from "react";
export class Menu extends Component {
constructor(props) {
super(props);
this.liRefs = [];
}
showSubmenu = (e) => {
// this.liRefs.current.style.display = "block";
for (var i = 0; i < this.liRefs.length; i++) {
this.liRefs[i].current.style.display = "block";
}
// console.log(this.liRefs[10]);
};
getStyle = (e) => {
e.target.style.background = "red";
};
render() {
return (
<ul className="mainmenu">
{this.props.items.map((i) =>
i.subitems ? (
<li key={i.id} onMouseOver={this.showSubmenu}>
{i.icon}
{i.name}
<ul key={i.id} ref={(ref) => (this.liRefs[i.id] = ref)}>
{i.subitems.map((item) => (
<div key={item.id} className="submenu">
{item.icon}
{item.name}
</div>
))}
</ul>
</li>
) : (
<li key={i.id}>
{i.icon}
{i.name}
{i.img}
</li>
)
)}
</ul>
);
}
}
export default Menu;
You are giving ref value to this. liRefs[i.id] and accessing through this. liRefs[i] so that both are the different change your code as below:
{this.props.items.map((i,index) =>
i.subitems ? (
<li key={i.id} onMouseOver={this.showSubmenu}>
{i.icon}
{i.name}
<ul key={i.id} ref={(ref) => (this.liRefs[i.id] = ref)}>
{i.subitems.map((item) => (
<div key={item.id} className="submenu">
{item.icon}
{item.name}
</div>
))}
</ul>
</li>
) : (
<li key={i.id}>
{i.icon}
{i.name}
{i.img}
</li>
)
)}

binding multiple ul li subcategeries under categeries

I have some categories list, I have to develop dynamic dropdown based on user click I have to call API and need to bind subcategories under categories.
I have to bind subcategories for particular li but it binding for every category li.
till now I have tried this,
subCategeries = ({subCategeries, index}) => {
return (
<ul>
{subCategeries.map(subCategeries => {
return (<li key={subCategeries.id} onClick={(event) => {
this.getSubSubCategeries(event, subCategeries.id)
}}>
{subCategeries.name}
<this.subSubCategeries subSubCategeries={this.state.subSubCategeries}/>
</li>);
})}
</ul>
);
};
subSubCategeries = ({subSubCategeries}) => {
return (
<ul>
{subSubCategeries.map(subSubCategeries => {
return (<li key={subSubCategeries.id}>
{subSubCategeries.name}
</li>);
})}
</ul>
);
};
render() {
var self = this;
console.log(self);
var mainCategeries = this.state.mainCategeries && this.state.mainCategeries.length > 0 && this.state.mainCategeries.map((obj, index) =>
<li key={index}><a onClick={(event) => {
this.getSubCategeries(event, obj.id)
}}>{obj.name}
{this.state.subCategeries.length > 0 ? (
<this.subCategeries index={index} subCategeries={this.state.subCategeries}/>)
: ''
}
</a>
</li>);
return (
<ul>{mainCategeries}
</ul>
);
}

Gettign error while returning elements in render() function React+redux

I want to print list as per the condition like
If I have 2 set of track's
1 ) featured
2) nonFeatured
if featured track is available then i want to append
<li>Featured Track</li>
before feature track list.
and if nonFeatured tracks are available then
<li> Other tracks</li>
before the list
So the output will be -
<ul>
<li>Featured Track</li>
<li>1</li>
<li>2</li>
<li>Other tracks</li>
<li>1</li>
</ul>
Below is my code snippet.
render() {
// Feature tracks and tracks are sorted track lists from currentTracks array. CurrentTracks contains both types.
let {featureTracks, tracks, currentTracks} = this.props.currentTracks
let errorMessage = currentTracks.error
let races = null
if(_.isArray(currentTracks.tracks) && !_.isEmpty(currentTracks.tracks)) {
races = (
<ul className="currentRacesDropdownList animated">
//Code to return feature track
if(_.isArray(featureTracks) && !_.isEmpty(featureTracks)) {
return (
<li className="dropDownHeading ttFont fontRed">
Featured Tracks (5)
</li>
{ featureTracks.map((track, key) => <RaceLineItem key={key} track={track} /> )}
)
}
if(_.isArray(tracks) && !_.isEmpty(tracks)) {
//Code to return other track
return (
<li className="dropDownHeading ttFont fontRed">
All Other Tracks (5)
</li>
{ tracks.map((track, key) => <RaceLineItem key={key} track={track} /> )}
)
}
</ul>
)
}
return (
<div>
{races}
{errorMessage}
</div>
)
}
But I am getting error in return statement after if()
Just same question in other way please have a look at below example .
I have below array , and if track is feature then i want to print it under "Feature" headline , and if track is non feature then i want to print it under "Other" headline.
var a = [{
isFeature:true,
name: 'abc'
},{
isFeature:false,
name: 'xyz'
},{
isFeature: false,
name: 'bpl'
}]
And on react I want to render it in below html format -
<ul>
<li>Feature</li>
<li>abc</li>
<li>xyz</li>
<li>Non Feature</li>
<li>bpl</li>
</ul>
You can use map() and filter() methods to do it on a cleaner way. You can try something like this :
let a = [{
isFeature:true,
name: 'abc'
},{
isFeature:false,
name: 'xyz '
},{
isFeature: false,
name: 'bpl'
}]
class Test extends React.Component {
render() {
let data = this.props.data;
let races = null;
if(data.length > 0){
races = <div>
<div>Featured</div>
{data.map(item => item).filter(f => f.isFeature)}
<div>Non featured</div>
{data.map(item => item).filter(f => !f.isFeature)}
</div>
}
return races
}
}
React.render(<Test data={a}/>, document.getElementById('container'));
Here is fiddle.
UPDATE
Now the results will be shown only if they exists.
let a = [{
isFeature:true,
name: 'abc'
},{
isFeature:false,
name: 'xyz '
},{
isFeature: false,
name: 'bpl'
}]
class Test extends React.Component {
render() {
let data = this.props.data;
let races = null;
if(data.length > 0){
let featured = data.map(item => item).filter(f => f.isFeature).length > 0 ? <div><div>Featured</div>{data.map(item => item).filter(f => f.isFeature)}</div> : "";
let nonFeatured = data.map(item => item).filter(f => !f.isFeature).length > 0 ? <div><div>Non Featured</div>{data.map(item => item).filter(f => !f.isFeature)}</div> : "";
races = <div>
{featured}
{nonFeatured}
</div>
}
return races
}
}
React.render(<Test data={a}/>, document.getElementById('container'));
Fiddle.
You cannot mix JSX with arbitrary statements like if...else or returns.
Instead, use a ternary expression:
<ul className="currentRacesDropdownList animated">
{(_.isArray(featureTracks) && !_.isEmpty(featureTracks)) ?
<span>
<li className="dropDownHeading ttFont fontRed">
Featured Tracks (5)
</li>
{ featureTracks.map((track, key) => <RaceLineItem key={key} track={track} /> )}
</span>
: null}
...
</ul>

Resources