componenet does not re-render after change in state in react.js - reactjs

i have an eCommerce application i want the quantity of an item in shopping cart** to be increased as user clicks on plus icon , but when the user clicks on the item state changes but the component doesn't re-renders there for not updating the quantity number in shopping cart , but as i refresh the page the number is updated
main code:
const [item, setItems] = useState([]);
useEffect(() => {
setItems(items);
}, []);
const handlePlus = (number, index) => {
let Nnumber = (number += 1);
let changeitems = item;
changeitems[index].qty = Nnumber;
setItems(changeitems);
localStorage.setItem("items", JSON.stringify(changeitems));
};
JSX:
<span onClick={(e) => {
handlePlus(eachItem.qty, index);
}}
>
<i className="bi bi-plus-circle-fill text-success"></i>{" "}
</span>
Complete code
import { Fragment, useState, useEffect } from "react";
const Cartitemscreater = ({ items ,cartUpdater}) => {
const [total, setTotal] = useState(0);
const [item, setItems] = useState([]);
const [available,setAvailable] = useState(true)
useEffect(() => {
setItems(items);
let totalPr = 0;
for (let index = 0; index < items.length; index++) {
let price = parseInt(items[index].productprice);
totalPr += price * items[index].qty;
}
setTotal(totalPr);
}, []);
let changeItems = []
const handlePlus = (number, index) => {
let Nnumber = (number += 1);
changeItems = item;
changeItems[index].qty = Nnumber;
setItems(changeItems);
localStorage.setItem("items", JSON.stringify(changeItems));
};
const handleMinus = (number, index) => {
let Nnumber = (number -= 1);
let changeitems = item;
changeitems[index].qty = Nnumber;
setItems(changeitems);
localStorage.setItem("items", JSON.stringify(changeitems));
};
const handleDelete = (_id,index)=>{
let deleteState = []
for (let index = 0; index < item.length; index++) {
if(item[index]._id!==_id){
deleteState.push(item[index])
}
}
setItems(deleteState)
cartUpdater(deleteState.length)
if(deleteState.length===0){
setAvailable(false)
return localStorage.removeItem("items")
}
localStorage.setItem("items",JSON.stringify(deleteState))
}
return (
<Fragment>
{ available ?<div className="container my-5">
<div className="table-responsive-xl">
<table class="table mt-5 ">
<thead>
<tr>
<th scope="col">Product image</th>
<th scope="col">Product title</th>
<th scope="col">Product price</th>
<th scope="col">Product quantity </th>
</tr>
</thead>
{ item.map((eachItem, index) => {
return (
<tbody key={eachItem._id} className="shadow">
<tr>
<td>
<img
src={`/products/${eachItem._id}/${eachItem.prImage}`}
className="img-fluid imgs "
alt="somethings"
style={{
width: "130px",
height: "80px",
objectFit:"cover"
}}
/>
<p><small className="text-muted">{eachItem.productdescription}</small></p>
<span onClick={()=>{
handleDelete(eachItem._id,index)
}}><i class="bi bi-trash fs-4 text-danger"></i></span>
</td>
<td>{eachItem.producttitle}</td>
<td className="fw-bold">$ {eachItem.productprice}</td>
<td>
<span
onClick={(e) => {
handleMinus(eachItem.qty, index);
}}
>
{" "}
<i className="bi bi-dash-circle-fill text-danger"></i>
</span>
<span className="mx-2"> {eachItem.qty}</span>
<span
onClick={(e) => {
handlePlus(eachItem.qty, index);
}}
>
<i className="bi bi-plus-circle-fill text-success"></i>{" "}
</span>
</td>
</tr>
</tbody>
);
})}
</table>
</div>
</div>: <p className="mt-lg-5 fw-bold text-danger fs-4"> {"Cart is empty "}<i class="bi bi-cart-fill"></i> </p> }
</Fragment>
);
};
export default Cartitemscreater;

The number isn't updating because useState is async. React is not updating instant instead it is just putting the state update into a queue to avoid unnecessary re-renders. If you really need the update you can use this update function.
Example:
const useForceUpdate = () => {
const [value, setValue] = useState(0);
return () => setValue((value) => value + 1);
};
Just call it in the same click event.

Related

How to overwrite data on localStorage?

I'm building a store app where I can have a list of pokemon and data that belongs to each pokemon. I use localStorage to save my data. The data is like this on localStorage.
{
pokemonName: name,
pcs: stockPcs,
dozen: stockDozen,
dozenToPcs: stockDozenToPcs,
total: totalPcs,
history: [
{
date: new Date().toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }),
hour: new Date().getHours(),
minute: new Date().getMinutes(),
activity: '',
note: '',
count: 0,
totalStock: 0
}
]
}
my question is how do I overwrite the data from the same pokemon and add the history of data. I tried, but instead of overwriting, it adds a whole new object with the same pokemon name (but different data.
I want to add new data only on history array so i can track it.
I want to overwrite pcs, dozen, dozenToPcs, and total properties.
Where is my mistake and what should I do to achieve this? Thank you so much.
import React, { useEffect, useState } from 'react'
import Button from 'react-bootstrap/Button';
import prevPageIcon from '../images/prevPage.svg'
import { Table, Modal, Container, Row, Col, Form } from 'react-bootstrap';
import { useNavigate, useParams } from 'react-router-dom'
This is where I input my data:
function UpdateStockModal(props) {
let { name } = useParams()
const [input, setInput] = useState({})
let stockPcs = 1 * input.pcs
let stockDozen = 1 * input.dozen
let stockDozenToPcs = 12 * input.dozen
let totalPcs = stockPcs + stockDozenToPcs
let navigate = useNavigate();
const handleChange = e => {
let newValue = {
...input,
[e.target.name]: e.target.value,
};
setInput(newValue);
};
const saveChange = () => {
navigate(`/update-stock/${name}`)
var pokemonData = [];
pokemonData = JSON.parse(localStorage.getItem("pokemon") || "[]");
pokemonData.push({
pokemonName: name,
pcs: stockPcs,
dozen: stockDozen,
dozenToPcs: stockDozenToPcs,
total: totalPcs,
history: [
{
date: new Date().toLocaleDateString('en-GB', { day: 'numeric', month: 'short', year: 'numeric' }),
hour: new Date().getHours(),
minute: new Date().getMinutes(),
activity: '',
note: '',
count: 0,
totalStock: 0
}
]
})
localStorage.setItem('pokemon', JSON.stringify(pokemonData));
}
return (
<Modal
{...props}
size="lg"
aria-labelledby="contained-modal-title-vcenter"
className="modal"
centered
>
<Modal.Header closeButton>
<Modal.Title className="modal-title">
Update stock
</Modal.Title>
</Modal.Header>
<Modal.Body>
<h4>Masukkan jumlah stok yang tersedia di rak saat ini.</h4>
<Container>
<Row>
<Col>Kemasan</Col>
<Col>Jumlah</Col>
<Col>Stok</Col>
</Row>
<Row className="modal-table-body">
<Col >Pcs</Col>
<Col className="d-flex align-items-center">1 x <Form.Control className="modal-input pcs" type="number" name="pcs" value={input.pcs} onChange={handleChange} /> = </Col>
<Col>{input.pcs || 0}</Col>
</Row>
<Row className="modal-table-body">
<Col>Lusin</Col>
<Col className="d-flex align-items-center">12 x <Form.Control name="dozen" className="modal-input dozen" type="number" value={input.dozen} onChange={handleChange} /> = </Col>
<Col>{12 * input.dozen || 0}</Col>
</Row>
<Row className="modal-table-body">
<Col>Total Stok <span>(dalam pcs)</span></Col>
<Col>Lusin</Col>
<Col>{(12 * input.dozen) + (1 * input.pcs) || 0}</Col>
</Row>
</Container>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
onClick={saveChange} >
Simpan
</Button>
<Button
variant="secondary"
onClick={saveChange}>
Batal
</Button>
</Modal.Footer >
</Modal >
);
}
export default function PokemonDetail() {
let navigate = useNavigate();
let { name } = useParams()
const [modalShow, setModalShow] = useState(false);
const [pokemonData, setPokemonData] = useState([])
useEffect(() => {
let pokemonData = JSON.parse(localStorage.getItem('pokemon') || "[]");
console.log(pokemonData, "ini di detail")
setPokemonData(pokemonData)
}, [])
return (
<div className="pokemon-detail-page">
<div className="pokemon-detail_button-group">
<Button variant="outline-light" className="prev-button" onClick={() => {
navigate('/')
}}><img src={prevPageIcon}></img>Stok Pokémon</Button>
<Button className="update-stock-button" onClick={() => setModalShow(true)}>Update Stok</Button>
</div>
<p className="pokemon-detail-title" style={{ textTransform: 'capitalize' }}>{name}</p>
<div className="pokemon-detail-subtitle">
<p className="pokemon-detail-sub1">Sisa Stok</p>
<p className="pokemon-detail-sub2">10 pcs</p>
</div>
<div className="pokemon-detail-history">
<p className="pokemon-detail-history1">Riwayat Stok</p>
<p className="pokemon-detail-history2">Satuan stok dalam pcs</p>
</div>
<div>
<Table className='col-xs-12 mt-4' responsive>
<thead>
<tr className="th-border ">
<th scope="col">Waktu</th>
<th scope="col">Kegiatan</th>
<th scope="col">Catatan</th>
<th scope="col">Jumlah</th>
<th scope="col">Stok</th>
</tr>
</thead>
<tbody>
{
pokemonData.map(pokemon => {
if (pokemon.pokemonName == name) {
console.log(pokemon.history[0].date, "pokemon di update")
return (
<tr className="align-items-center">
<td className="">{`${pokemon.history[0].date}, ${pokemon.history[0].hour}:${pokemon.history[0].minute}`}</td>
<td className="table-link">Update Stok</td>
<td className=""></td>
<td className="table-count-stock">+10</td>
<td className="table-bold">10</td>
</tr>
)
}
})
}
</tbody>
</Table>
</div>
<UpdateStockModal
show={modalShow}
onHide={() => setModalShow(false)}
/>
</div >
)
}
This is where I show my data:
function EditStockModal(props) {
let { name } = useParams()
const [input, setInput] = useState({})
// let stockPcs = 1 * input.pcs
// let stockLusin = 1 * input.lusin
// let stockLusinToPcs = 12 * input.lusin
// let totalPcs = stockPcs + stockLusinToPcs
let navigate = useNavigate();
const handleChange = e => {
let newValue = {
...input,
[e.target.name]: e.target.value,
};
setInput(newValue);
};
const saveChange = () => {
navigate(`/update-stock/${name}`)
var pokemonData = [];
pokemonData = JSON.parse(localStorage.getItem("pokemon") || "[]");
localStorage.setItem('pokemon', JSON.stringify(pokemonData));
}
}
export default function UpdateStock() {
let { name } = useParams()
const [pokemonData, setPokemonData] = useState([]);
const [note, setNote] = useState({})
let navigate = useNavigate();
const [modalShow, setModalShow] = useState(false);
useEffect(() => {
let pokemon = JSON.parse(localStorage.getItem('pokemon'));
setPokemonData(pokemon)
console.log(pokemon, "ini data apa")
// if (pokemonData) {
// pokemonData.map(pokemon => {
// setPokemonData(pokemonData);
// })
// }
}, []);
const handleChange = e => {
let newValue = {
...note,
[e.target.name]: e.target.value,
};
// console.log(newValue)
// setNote(newValue);
};
// function updateNote(updatedData) {
// const pokemonUpdatedData = {
// ...JSON.parse(localStorage.getItem('pokemon')),
// ...updatedData
// };
// localStorage.setItem('pokemon', JSON.stringify(pokemonUpdatedData));
// }
const saveChange = () => {
navigate(`/pokemon/${name}`)
console.log(pokemonData, "//arr kosong")
// pokemonData.push({
// pokemonName: name,
// pcs: stockPcs,
// lusin: stockLusin,
// lusinToPcs: stockLusinToPcs,
// total: totalPcs,
// history: [
// {
// date: new Date().toLocaleString(),
// activity: '',
// note: note,
// count: totalPcs - count,
// totalStock: totalPcs + count
// }
// ]
// })
// updateNote(pokemonData)
}
return (
<div className="update-stock-page">
<h1 className="update-stock-title">Konfirmasi update stok</h1>
{
pokemonData.map((pokemon, i) => {
if (pokemon.pokemonName == name) {
console.log(pokemon.pokemonName, "pokemonName", name, "name")
return (
<>
<div>
<p className="update-stock-subtitle">Selisih</p>
<p className="update-stock-difference">{`${pokemon.total} pcs`}</p>
</div>
<div className="row d-flex justify-content-center ">
<div className="col">
<p>Di sistem</p>
<p>{`10 pcs`}</p>
</div>
<div className="col-1 align-center ">
<img width="21" height="21" src={arrowIcon} />
</div>
<div className="col">
<p>Hasil update stok</p>
<p>544 pcs</p>
</div>
</div>
</>
)
}
})
}
<Table className='col-xs-12 mt-4' responsive>
<thead>
<tr className="th-border">
<th scope="col">Keterangan</th>
<th scope="col">Detail</th>
<th scope="col">Jumlah</th>
</tr>
</thead>
<tbody>
{
pokemonData.map(pokemon => {
if (pokemon.pokemonName == name) {
console.log(pokemon.pokemonName, "pokemonName di confirm", name, "name di confirm")
return (
<>
<tr className="align-items-center">
<td className="table-link">Hasil update stock</td>
<td className="">{`${pokemon.pcs} pcs, ${pokemon.dozen} lusin (12s)`}</td>
<td className="">{pokemon.total}</td>
<td>
<img src={editIcon} onClick={() => setModalShow(true)}></img>
</td>
</tr>
<tr className="align-items-center">
<td className="table-link">Total hasil stok opname</td>
<td></td>
<td className="">{pokemon.total}</td>
</tr>
</>
)
}
})
}
</tbody>
</Table>
<div className="update-stock-note-group">
<p className="update-stock-note-title">Catatan</p>
<textarea className="update-stock-note-input" onChange={handleChange} placeholder="Contoh: stok awal"></textarea>
</div>
<div className="d-flex justify-content-end gap-2">
<Button variant="primary" onClick={saveChange}>Simpan</Button>
<Button variant="secondary">Batal</Button>
</div>
</div>
)
}

How to toggle in a map function in React?

I try to load user history and show it inside a table.
Inside this table should be a button with "show more"
This button is a dropdown toggle button.
Everything working so far but when i click the button that is inside a map function all dropdowns open at the same time.
I know i've to use an index in the map function but I've no clue how i can use this index for my dropdown state.
import React, { useEffect, useState } from 'react';
import axios from 'axios';
import { useSelector } from 'react-redux';
function OrderHistory() {
const [history, setHistory] = useState([]);
const [dropdown, setDropdown] = useState(false);
const auth = useSelector((state) => state.auth);
const token = useSelector((state) => state.token);
const { user } = auth;
useEffect(() => {
const getHistory = async () => {
const res = await axios.get('/user/history', {
headers: { Authorization: token },
userid: user._id,
});
setHistory(res.data);
};
getHistory();
}, [token, setHistory]);
console.log(history);
const clickHandler = (index) => (event) => {
//event.preventDefault();
setDropdown(!dropdown);
console.log('clicked');
};
return (
<div className='history-page h-screen'>
<h2>History</h2>
<h4>You have {history.length} ordered</h4>
<table>
<thead>
<tr>
<th>Bestellnummer</th>
<th>Datum</th>
<th>Summe</th>
<th>Details</th>
</tr>
</thead>
<tbody>
{history.map((items, index) => (
<tr key={items._id}>
<td>
{items._id}
</td>
<td>{new Date(items.createdAt).toLocaleDateString()}</td>
<td>
{(
Math.round(
items.cartItems.reduce((x, item) => x + item.price, 0) * 100
) / 100
).toFixed(2)}
€
</td>
<td>
<button
class='bg-yellow-500 hover:bg-yellow-400 text-white font-bold py-2 px-4 rounded'
key={index}
onClick={clickHandler(index)}
>
Show more
</button>
<div className={dropdown ? '' : 'hidden'}>
<div>{items.firstName}</div>
</div>
</td>
</tr>
))}
</tbody>
</table>
</div>
);
}
export default OrderHistory;
Initialize the dropdown state with null.
const [dropdown, setDropdown] = useState(null);
In clickHandler store, i just store the index.
const clickHandler = (index) => {
setDropdown((prev) => {
return prev === index ? null : index;
});
console.log('clicked', index);
};
Now in map function, check where you apply the condition to show the dropdown. I check if the dropdown is equal to that index, then that dropdown will visible otherwise add hidden class.
You can also use _id to show/hide dropdown instead of index
<td>
<button
class='bg-yellow-500 hover:bg-yellow-400 text-white font-bold py-2 px-4 rounded'
key={index}
onClick={() => clickHandler(index)}
>
Show more
</button>
<div
className={dropdown === index ? '' : 'hidden'}
// style={{ display: dropdown === index ? 'block' : 'none' }}
>
<div>{items.firstName}</div>
</div>
</td>

React: Updating multiple object variables in array

I want to implement a voting system in my app where you can vote thumbs-up or thumbs-down for a selected movie. The ratings will be saved in a ratings array of objects that contain movie title, id, thumbs-up votes and thumbs-down votes. If a movie has no votes, the first vote will add the new object into the ratings array, and subsequent votes will update the thumbs-up votes and thumbs-down votes of the object. My current code works for the first thumbs-up vote and adds the new obj into the array, but does not update the vote count for subsequent votes. How can I update the votes in the movie object for both thumbs-up and thumbs-down votes? This involves incrementing the count depending on whether the thumbs-up or thumbs-down button is clicked. How can I handle this besides creating separate but similar functions for each button like I’ve already started to do? Any help is greatly appreciated, thank you in advance!
const ThumbRating = ( {id, title} ) => {
const [thumbsUpCount, setthumbsUpCount] = useState(0);
const [thumbsDownCount, setthumbsDownCount] = useState(0);
const [ratings, setRatings] = useState([]);
const newUpVote = (id) => {
if (thumbsUpCount === 0 && thumbsDownCount === 0) {
setthumbsUpCount(thumbsUpCount + 1);
const obj = {
id: {id},
title: {title},
thumbsUpCount: thumbsUpCount +1,
thumbsDownCount: thumbsDownCount
}
setRatings([obj])
} else {
setthumbsUpCount(thumbsUpCount +1)
handleThumbsUp(id, thumbsUpCount +1)
}
}
const handleThumbsUp = (id, thumbsUpCount) => {
setRatings(ratings.map(obj => {
if (obj.id !== id) return obj
return {...obj, thumbsUpCount: thumbsUpCount +1}
}))
}
return (
<div className="thumb-rating">
<p>Would you recommend this movie?</p>
<table>
<tbody>
<tr>
<td>
<div >
<button className="thumbs-up" onClick={() => newUpVote(id)}>
<i className="fa fa-thumbs-up fa-4x" />
</button>
</div>
</td>
<td>
<div >
<button className="thumbs-down" onClick={() => setthumbsDownCount(thumbsDownCount + 1)}>
<i className="fa fa-thumbs-down fa-4x" />
</button>
</div>
</td>
</tr>
<tr>
<td>
<h2>Yes: {thumbsUpCount} </h2>
</td>
<td>
<h2>No: {thumbsDownCount} </h2>
</td>
</tr>
</tbody>
</table>
</div>
)
}
There is My solution:
The handlerHandleCountDown is working and the state is correcting updating.
Now you can try to handle the countDown based on the example.
Do not forget to pass id and title as props to your component. 🙂
import { useState } from 'react'
const ThumbRating = ({ id, title }) => {
const [thumbsUpCount, setthumbsUpCount] = useState(0)
const [thumbsDownCount, setthumbsDownCount] = useState(0)
const [ratings, setRatings] = useState([])
const newUpVote = (id) => {
if (thumbsUpCount === 0 && thumbsDownCount === 0) {
setthumbsUpCount(thumbsUpCount + 1)
const obj = {
id, // id:id also works but id: {id} will not
title,
thumbsUpCount: thumbsUpCount + 1,
thumbsDownCount: thumbsDownCount,
}
setRatings([obj])
} else {
setthumbsUpCount(thumbsUpCount + 1)
handleThumbsUp(id)
}
}
const handleThumbsUp = (id) => {
// Is better to use the find method when you want to find a single element in an array
const objectToBeUpdated = ratings.find((obj) => obj.id === id)
objectToBeUpdated.thumbsUpCount += 1 // I assumed you will always update by one
setRatings([objectToBeUpdated])
}
return (
<div className='thumb-rating'>
<p>Would you recommend this movie?</p>
<table>
<tbody>
<tr>
<td>
<div>
<button className='thumbs-up' onClick={() => newUpVote(id)}>
<i className='fa fa-thumbs-up fa-4x' />
</button>
</div>
</td>
<td>
<div>
<button
className='thumbs-down'
onClick={() => setthumbsDownCount(thumbsDownCount + 1)}
>
<i className='fa fa-thumbs-down fa-4x' />
</button>
</div>
</td>
</tr>
<tr>
<td>
<h2>Yes: {thumbsUpCount} </h2>
</td>
<td>
<h2>No: {thumbsDownCount} </h2>
</td>
</tr>
</tbody>
</table>
</div>
)
}
export default ThumbRating

uploading data to table getting no result

hello iam following mosh hamedani course at some point i got stuck in uploading data in table
this is my table where title and genre is uploading where in stock and rate these are number not string are not uploading here is my table body
class TableBody extends Component {
render() {
const {data,columns} = this.props
console.log({data,columns})
return ( <tbody>
{data.map(item => <tr key={item._id}>
{columns.map(column => <td key={item._id + (column.path || column.key)}>{_.get(item,column.path)}</td>)}
</tr>
)}
</tbody>
);
}
}
data and columns are coming from movietable component here is the code
class MovieTable extends Component {
columns =[
{ path:'title',label:'Title'},
{ path:'genre.name',label:'Genre'},
{ path:'numberInstock',label:'stock'},
{ path:'dailyReantalRate',label:'Rate'},
{ key: 'like' },
{key: 'delete' }
];
render() {
const {movies, onDelete,onSort ,onLike,sortColumn,onAdd,deleted} = this.props;
return (
<table className="table">
<TableHeader columns={this.columns} sortColumn={sortColumn} onSort={onSort}/>
<TableBody data={movies} columns={this.columns}/>
<tbody>
{movies.map((movie) => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
{" "}
<Like
liked={movie.liked}
onClick={() => onLike(movie)}
/>{" "}
</td>
<td
onClick={() => onDelete(movie._id)}
className="btn btn-danger btn-outline-warning btn-sm active "
>
Remove
</td>
</tr>
))}
</tbody>
<tbody>
{deleted.map((movie) => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
{" "}
<Like />{" "}
</td>
<td
onClick={() => onAdd (movie._id)}
className="btn btn-danger btn-outline-primary btn-sm active "
>
ADD
</td>
</tr>
))}
</tbody>
</table>
);
}
}
movies from props coming from its parent movies component here is movies component code
class Movies extends Component {
state = {
movies:[],
deleted: [],
genres:[],
pageSize: 9,
currentPage:1,
sortColumn:{
path:'title',
order:'asc'
}
};
componentDidMount(){
const genres =[{ _id:"",name:'All Genres'},...getGenres()]
this.setState({
movies:getMovies(),
genres
})
}
handleDelete = (_id) => {
const movie = this.state.movies.find((x) => x._id === _id);
this.setState({ deleted: [...this.state.deleted, movie] });
this.setState({ movies: this.state.movies.filter((x) => x._id !== _id) });
};
handleLike = (m) => {
const movies = [...this.state.movies];
const index = movies.indexOf(m);
movies[index] = { ...movies[index] };
movies[index].liked = !movies[index].liked;
this.setState({ movies });
};
handleReinstate = (_id) => {
const movie = this.state.deleted.find((movie) => movie._id === _id);
this.setState({ movies: [...this.state.movies, movie] });
this.setState({
deleted: this.state.deleted.filter((movie) => movie._id !== _id),
});
};
handleGenreSelect = genre => {
this.setState({selectedGenre:genre, currentPage:1})
}
handleSort= sortColumn =>{
this.setState({sortColumn});
}
render() {
const { pageSize,currentPage,sortColumn,selectedGenre,movies:allMovies,deleted} = this.state;
const filtered = selectedGenre && selectedGenre._id ? allMovies.filter(m=>m.genre._id === selectedGenre._id ): allMovies;
const sorted = _.orderBy(filtered, [sortColumn.path],[sortColumn.order]);
const movies = paginate(sorted,currentPage,pageSize)
return (
<div className="row">
<div className="col-2">
<ListGroup items={this.state.genres} selectedItem={this.state.selectedGenre} onItemSelect={this.handleGenreSelect}/>
</div>
<div className="col">
<div className={this.getbadgesClasses()}> <p>there are {filtered.length} movies in our data base</p> </div>
<MovieTable
movies={movies}
onSort={this.handleSort}
onDelete={this.handleDelete}
onLike={this.handleLike}
deleted={deleted}
onAdd={this.handleReinstate}/>
<Pagination
itemCount={filtered.length}
pageSize={pageSize}
sortColumn={sortColumn}
onPageChange={this.handlePageChange}
currentPage={currentPage}
/>
</div>
</div>
);
}
getbadgesClasses() {
let classes = " badge m-2 badge-";
classes += this.state.movies.length === 0 ? "warning" : "primary";
return classes;
}
handlePageChange = (page) => {
this.setState({currentPage: page})
};
}
this is my console.log
i have give aerong path to Columns array its like spelling mistake in path

Remove table row using Hooks

I'm new to react and learning hooks. I found examples online that im converting to use hooks as practice but running into an issue with one. The example i'm converting, I can't figure out why the "Remove" button for function handleRemoveSpecificRow on the table row doesn't work. It should remove the the row. I'm stuck at this point. Any help appreciated.
Demo: https://codesandbox.io/s/zq185w2zkm
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Button, Input } from "reactstrap";
function App() {
const [rows, setRows] = useState([{}]);
const handleChange = index => e => {
const { name, value } = e.target;
const rows = [...rows];
rows[index] = {
[name]: value
};
setRows(rows);
};
const handleAddRow = () => {
const item = {
column_1: "",
column_2: ""
};
setRows([...rows, item]);
};
const handleRemoveRow = () => {
setRows(rows.slice(0, -1));
};
const handleRemoveSpecificRow = index => () => {
const rows = [...rows];
rows.slice(index, 1);
setRows(rows);
};
return (
<div>
<Table>
<thead className="thead-light">
<tr>
<th>#</th>
<th>Column 1</th>
<th>Column 2</th>
<th />
</tr>
</thead>
<tbody>
{rows.map((item, index) => (
<tr id="addr" key={index}>
<td>{index}</td>
<td>
<Input
type="text"
name="name"
value={rows[index].column_1}
onChange={handleChange(index)}
/>
</td>
<td>
<Input
type="text"
name="mobile"
value={rows[index].column_2}
onChange={handleChange(index)}
/>
</td>
<td>
<Button
outline
color="danger"
onClick={handleRemoveSpecificRow(index)}
>
Remove
</Button>
</td>
</tr>
))}
</tbody>
</Table>
<Button onClick={handleAddRow}>Add Row</Button>
<Button color="danger" onClick={handleRemoveRow}>
Delete Row
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
I too had my fair share of doubts like this, focus towards array/object manipulation techniques. Always manipulate data in a controlled way using unique id, key, etc..
https://codesandbox.io/s/y2lqj9qnjz
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Button, Input } from "reactstrap";
function App() {
const [rows, setRows] = useState([]);
const handleChange = item => e => {
const { name, value } = e.target;
// const rows = [...rows];
// rows[index] = {
// [name]: value
// };
let items = rows.map(row => {
if (row.id === item.id) {
row[name] = value;
}
return row;
});
setRows(items);
};
const handleAddRow = () => {
let item = {
id: rows.length + 1,
column_1: "",
column_2: ""
};
setRows([...rows, item]);
};
const handleRemoveRow = () => {
setRows(rows.slice(0, -1));
};
const handleRemoveSpecificRow = item => () => {
// const rows = [...rows];
// rows.splice(index, 1);
// setRows(rows);
let items = rows.filter(row => row.id != item.id);
setRows(items);
};
console.log(rows);
return (
<div>
{rows.length != 0 && (
<Table>
<thead className="thead-light">
<tr>
<th>#</th>
<th>Column 1</th>
<th>Column 2</th>
<th />
</tr>
</thead>
<tbody>
{rows.map((item, index) => (
<tr id="addr" key={index}>
<td>{item.id}</td>
<td>
<Input
type="text"
name="column_1"
value={item.column_1}
onChange={handleChange(item)}
/>
</td>
<td>
<Input
type="text"
name="column_2"
value={item.column_2}
onChange={handleChange(item)}
/>
</td>
<td>
<Button
outline
color="danger"
onClick={handleRemoveSpecificRow(item)}
>
Remove
</Button>
</td>
</tr>
))}
</tbody>
</Table>
)}
<Button onClick={handleAddRow}>Add Row</Button>
<Button color="danger" onClick={handleRemoveRow}>
Delete Row
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
https://codesandbox.io/s/y2lqj9qnjz
I've updated the link above.
import React, { useState } from "react";
import ReactDOM from "react-dom";
import { Table, Button, Input } from "reactstrap";
function App() {
const [rows, setRows] = useState([
{
id: 1,
column_1: "",
column_2: ""
}
]);
const handleChange = (item) => (e) => {
const { name, value } = e.target;
// const rows = [...rows];
// rows[index] = {
// [name]: value
// };
let items = rows.map((row) => {
if (row.id === item.id) {
row[name] = value;
}
return row;
});
setRows(items);
};
const handleAddRow = () => {
let item = {
id: rows[rows.length - 1].id + 1,
column_1: "",
column_2: ""
};
setRows([...rows, item]);
};
const handleRemoveRow = () => {
setRows(rows.slice(0, -1));
};
const handleRemoveSpecificRow = (item) => () => {
// const rows = [...rows];
// rows.splice(index, 1);
// setRows(rows);
let items = rows.filter((row) => row.id != item.id);
setRows(items);
};
return (
<div>
{rows.length != 0 && (
<Table>
<thead className="thead-light">
<tr>
<th>#</th>
<th>Column 1</th>
<th>Column 2</th>
<th />
</tr>
</thead>
<tbody>
{rows.map((item, index) => (
<tr id="addr" key={index}>
<td>{item.id}</td>
<td>
<Input
type="text"
name="column_1"
value={item.column_1}
onChange={handleChange(item)}
/>
</td>
<td>
<Input
type="text"
name="column_2"
value={item.column_2}
onChange={handleChange(item)}
/>
</td>
<td>
<Button
outline
color="danger"
onClick={handleRemoveSpecificRow(item)}
>
Remove
</Button>
</td>
</tr>
))}
</tbody>
</Table>
)}
<Button onClick={handleAddRow}>Add Row</Button>
<Button color="danger" onClick={handleRemoveRow}>
Delete Row
</Button>
</div>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

Resources