React - conditional table display - reactjs

I'm working on a react project where the user needs to fill out a form, and according to the "Number of Credits" input - a table should be rendered with some of its rows possibly hidden. My idea was to to set up an isHidden property in the table objects and switch it according to the user input. Then, render only the rows where isHidden = false.
For some reason it's not working, the table keep being rendered as a whole, regardless to the input. I also tried to console.log the rows object, and the isHidden is not changing. Does anybody have an idea?
Here is my code:
App.js:
import Form from './components/Form'
import { useState } from 'react'
import TableDisplay from './components/TableDisplay'
import Banner from './components/Banner'
const App = () => {
const [showBanner, setShowBanner]=useState(false)
const [FormData, setFormData] = useState([
{
id:1,
name:'',
credits:'',
}
])
const [rows, setRows] = useState([
{
id:1,
description:'',
semester:'',
prefix:'ENG',
number:'368/371',
grade:'',
editing:'',
isHidden:false,
},
{
id:2,
description:'',
semester:'',
prefix:'',
number:'',
grade:'',
editing:'',
isHidden:false,
},
{
id:3,
description:'',
semester:'',
prefix:'',
number:'',
grade:'',
editing:'',
isHidden:false,
},
])
const getFormInfo = (info) => {
const id = Math.floor(Math.random() * 10000) + 1
const newName = {id,...info}
setFormData([newName]);
const num = info.credits;
if (num > 40 && num < 70) {
setRows(rows.map((row) =>
row.id===3 ? {isHidden:!row.isHidden}: row
))
}
else if (num>70) {
setRows(rows.map((row) =>
row.id===3 || rows.id===2 ? {isHidden:!row.isHidden}: row
))}
console.log(rows);
}
return (
<>
<Form onAdd={getFormInfo}
onAdd2={() => setShowBanner(!showBanner)
}
/>
{showBanner ? <Banner FormData={FormData}/> : null}
{showBanner ? <TableDisplay rows={rows}/>: null}
</>
);
}
export default App;
Form.js:
import { useState } from "react"
const Form = ({ onAdd,onAdd2}) => {
const[name, setName] = useState('')
const[credits, setCredits] = useState('')
const onSubmit = (e) => {
e.preventDefault();
onAdd({name,credits})
setName('');
setCredits('');
}
return (
<form onSubmit={onSubmit} >
<div className="mb-3">
<label className="form-label">Student Name:</label>
<input value={name}
onChange={(e) =>
setName(e.target.value)}
type="text"
className="form-control"
id="exampleInputEmail1"
aria-describedby="emailHelp"/>
</div>
<div className="mb-3">
<label className="form-label">Total Transfer Credits:</label>
<input value={credits}
onChange={(e) =>
setCredits(e.target.value)}
type="number"
className="form-control"
id="exampleInputPassword1"/>
</div>
<button onClick={onAdd2}
type="submit" className="btn btn-primary">Submit</button>
</form>
)
}
export default Form
TableDisplay.js:
import TableRows from "./TableRows"
const TableDisplay = ({rows, onDelete}) => {
return (
<div>
<table className="table table-striped">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Description</th>
<th scope="col">Semester</th>
<th scope="col">Prefix</th>
<th scope="col">Number</th>
<th scope="col">Grade</th>
<th scope="col">Editing</th>
</tr>
</thead>
<tbody>
{rows.map((row) => {
return <TableRows
key={row.id}
row={row}
/>
})}
</tbody>
</table>
</div>
)
}
export default TableDisplay
TableRows.js:
import React from 'react'
const TableRows = ({row}) => {
return (
<>
<tr>
<td scope="row">{row.id}</td>
<td>{row.description}</td>
<td>{row.semester}</td>
<td>ENG</td>
<td>368/371</td>
<td>{row.grade}</td>
<td><button type="button" className="btn btn-warning">Edit</button></td>
</tr>
</>
)
}
export default TableRows
Thanks!

Related

Deleting necessary data (with checkbox) in React

Need to delete the data that is highlighted by the checkbox. When I click on the checkbox, in all checkboxes the done becomes: true, then false and i can't remove the highlights. When the remove function is worked, only the first element is deleted. How can write a remove function.
import React from "react";
import { useState } from "react";
const App = () => {
const [user, setUser] = useState([
{id:1, name:"Peter", surname:"Robinson"},
{id:2, name:"Ann", surname:"Walker"},
{id:3, name:"James", surname:"Allen"},
])
const [check, setCheck] = useState({done: false})
const remove = () => {
if (check.done) {
}
}
return <>
<table className="table table-bordered">
<thead>
<tr>
{Object.keys(user[0]).map((elm,i) => {
return <td key={i}>
{elm.charAt(0).toUpperCase() + elm.slice(1)}
</td>
})}
</tr>
</thead>
<tbody>
{
user.map((elem, ind) => {
return <tr key={ind}>
<td>{elem.id}</td>
<td>{elem.name}</td>
<td>{elem.surname}</td>
<td>
<input type="checkbox" name="" id="" onChange={() => setCheck({done: check.done ? false : true})}/>
</td>
</tr>
})
}
</tbody>
</table>
<button className="btn btn-primary ms-2" onClick={() => remove()}>Delete selected</button>
</>
}
export default App;
Thank you.
You should handle the checked state for each user independently, then delete the ones with the checked flag at true:
import React from 'react';
import { useState } from 'react';
const App = () => {
const [user, setUser] = useState([
{ id: 1, name: "Peter", surname: "Robinson", checked: false },
{ id: 2, name: "Ann", surname: "Walker", checked: false },
{ id: 3, name: "James", surname: "Allen", checked: false }
]);
const toggleCheck = (id) => {
const checkedIdx = user.findIndex((u) => u.id === id);
if (checkedIdx === -1) return;
const updatedUser = [...user];
updatedUser[checkedIdx].checked = !updatedUser[checkedIdx].checked;
setUser(updatedUser);
};
const remove = () => {
setUser([...user].filter((u) => !u.checked));
};
return (
<>
<table className="table table-bordered">
<thead>
<tr>
{Object.keys(user[0]).map((elm, i) => {
return (
<td key={i}>{elm.charAt(0).toUpperCase() + elm.slice(1)}</td>
);
})}
</tr>
</thead>
<tbody>
{user.map((elem, ind) => {
return (
<tr key={elem.id}>
<td>{elem.id}</td>
<td>{elem.name}</td>
<td>{elem.surname}</td>
<td>
<input
type="checkbox"
name=""
id=""
onChange={() => toggleCheck(elem.id)}
value={elem.checked}
/>
</td>
</tr>
);
})}
</tbody>
</table>
<button className="btn btn-primary ms-2" onClick={() => remove()}>
Delete selected
</button>
</>
);
};
export default App;
Here is the code to a working sandbox.

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 get output of table on page in reactjs

I create a table I get data from the database using the backend I just want to show the output of the table on the page the output will not be visible
This is the code of my table.js
//import Data from './TextForm';
function Table(props) {
console.log('type ', typeof (props.Data));
console.log('data ', props.Data)
return (
<table>
<thead>
<tr>
<th>Text No</th>
<th>TextArea</th>
</tr>
</thead>
<tbody>
{props.Data ?
Object.entries(props.Data).map((key,value)=> {
console.log('Key',key);
{
<tr key={value}>
<td>{key.textId}</td>
<td>{key.textArea}</td>
</tr>
}
})
: null
}
</tbody>
</table>
)
}
export default Table;
this is props. data where I get the data and define prop. data I get data from the backend I connected the frontend for getting and storing data
Edit
function TextForm(props) {
const [text, setText] = useState('');
const [submittext,setsubmittext]=useState(null);
const [Data,setData]=useState([]);
const handleOnClickUpperCase = () => {
var newText = text.toUpperCase();
setText(newText);
}
const handleOnClickLowerCase = () => {
var newText = text.toLowerCase();
setText(newText);
}
const handleOnChange = (e) => {
setText(e.target.value);
}
const handleOnPreview = (e) => {
e.preventDefault();
setsubmittext(text);
// console.log(text);
const ROOT_URL='https://localhost:7113/';
var formData={
Textarea:text
}
axios.post(`${ROOT_URL}api/demo-text`, formData, {
headers: {"Access-Control-Allow-Origin": "*", 'Content-Type': 'application/json'}
})
.then(function (response) {
console.log('successs')
//handle success
setData(response);
console.log('response ',Data);
})
.catch(function (response) {
console.log('error')
//handle error
console.log(response);
})
}
return (
<>
<div className="container">
<h1>{props.title}</h1>
<p>Enter Text Here:</p>
<div className="mb-3">
<textarea className="form-control" value={text} onChange={handleOnChange} id="mybox" rows="8"></textarea>
</div>
<Table Data={Data} />
{text === text.toLowerCase() ? <button className="btn btn-primary" onClick={handleOnClickUpperCase}>Convert to Upper Case</button> : <button className="btn btn-primary" onClick={handleOnClickLowerCase}>Convert to Lower Case</button>}
<button className="btn btn-primary mx-3" onClick={handleOnPreview}>submit</button>
</div>
<hr></hr>
<div className="container my-4" >
<h1>{props.sum}</h1>
<p>Text Word {text.split(" ").length} and Character is {text.length}</p>
<p>{0.008 * text.split(" ").length} Minutes to Read</p>
</div>
<hr></hr>
<div className="container my-4">
<h2>Preview Your Text</h2>
<p>{submittext}</p>
</div>
</>
)
}
the output of prop.data
here have iterator objects array so pls try the following the code see I created an example as your same array object as you shared img pls find an example here link.
import React from "react";
import ReactDOM from "react-dom";
const Data = {
data: {
result: [
{ textId: 1, textarea: "test" },
{ textId: 2, textarea: "1234" },
{ textId: 3, textarea: null },
{ textId: 4, textarea: null },
]
}
};
function Table(props) {
console.log("type ", typeof props.Data);
console.log("data ", props.Data);
return (
<table>
<thead>
<tr>
<th>Text No</th>
<th>TextArea</th>
</tr>
</thead>
<tbody>
{props?.Data?.data?.result?.map((item) => (
<>
<tr key={item.textId}>
<td>{item.textId}</td>
<td>{item.textarea}</td>
</tr>
</>
))}
</tbody>
</table>
);
}
function App() {
return (
<>
<Table Data={Data} />
</>
);
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
So you have to iterate over props.Data.data.result instead of props.Data, You don't need the Object.entries(),
and make the initial value of the Data = {} instead of [].
const [Data, setData] = useState({});
In the conditional JSX code, you need to check if the object has keys or not, and you don't need Object.entries method, just go with props.Data.data.result.map(), Also you have to return tr from the map method as #Usama mentioned.
{Object.keys(props.Data).length ?
props.Data.data.result.map((key,value)=> {
return (<tr key={value}>
<td>{key.textId}</td>
<td>{key.textArea}</td>
</tr>)
})
: null
}

Problem with UseEffect , this useEffect I am using runs infinitely even after all required data is fetched

I have used useEffect as below to get the relevant Guide ID for a given Tour ID , the code works fine but the problem is that this runs infinitely causing the system to slow down.I know there is way to limit the iterations of this but I am not clear as to how to apply in this.
The useEffect
useEffect(() => {
bookings.forEach(({ tourId }) => {
axios.get(`http://localhost:8070/assignedGuides/check/${tourId}`).then((res) =>{
if(res.data === true){
axios.get(`http://localhost:8070/assignedGuides/get/${tourId}`)
.then(res => {
setGuides(guides => ({
...guides,
[tourId]: res.data.guideId,
}));
})
}
})
});
}, [bookings]);
The code section the Tour ID is coming from.
{bookings.map((booking) =>(
<tr>
<th scope = "row">{number++}</th>
<td>{booking.tourId}</td>
<td>{booking.bookingDate}</td>
<td>{booking.arrivalDate}</td>
<td>{booking.country}</td>
{/* {GuideAssigned(booking.guideId)} */}
<td>{guides[booking.tourId]}</td>
useStates
const [bookings , setBookings] = useState([]);
const [guides, setGuides] = useState({});
Full Code
import { useEffect } from "react";
import { useState } from "react";
import axios from "axios";
import IndexHeader from "components/Headers/IndexHeader";
import IndexNavbar from "components/Navbars/IndexNavbar";
import DemoFooter from "components/Footers/DemoFooter";
import {
Label,
Input,
Button,
Row,
Col,
InputGroup,
InputGroupAddon,
InputGroupText,
FormGroup,
Alert,
Container,
} from "reactstrap";
import { useHistory } from "react-router";
function AssignGuide(){
const [bookings , setBookings] = useState([]);
const [guides, setGuides] = useState({});
useEffect(()=>{
axios.get("http://localhost:8070/bookings/").then((res) =>{
setBookings(res.data);
})
})
let history = useHistory();
var number = 1;
useEffect(() => {
if(bookings.length != 0) {
bookings.forEach(({ tourId }) => {
axios.get(`http://localhost:8070/assignedGuides/check/${tourId}`).then((res) =>{
if(res.data === true){
axios.get(`http://localhost:8070/assignedGuides/get/${tourId}`)
.then(res => {
setGuides(guides => ({
...guides,
[tourId]: res.data.guideId,
}));
})
}
})
});
}
},[bookings]);
return(
<div>
<IndexNavbar />
<IndexHeader />
<h3 style ={{marginLeft:"40px"}}>Assigned Guides</h3><br/><br/>
<Row>
<Col>
<FormGroup>
<InputGroup style = {{marginLeft : "40px"}} className="form-group-no-border">
<InputGroupAddon addonType="prepend">
<InputGroupText>
<i className="nc-icon nc-zoom-split" />
</InputGroupText>
</InputGroupAddon>
<Input placeholder="Search " type="text"
/>
</InputGroup>
</FormGroup>
</Col>
<Col>
<div>
<Label style = {{marginLeft : "40px"}} check>
<Input type="checkbox"/>{" "}
<label style ={{marginRight : "40px"}}>Tour ID</label>
</Label>
</div>
</Col>
<Col></Col>
</Row>
<div style = {{marginLeft:"20px"}} className = "tableContainer">
<table className = "table table-striped">
<thead>
<th scope = "col">#</th>
<th scope = "col">Tour ID</th>
<th scope = "col">Booking Date</th>
<th scope = "col">Arrival Date</th>
<th scope = "col">Country </th>
<th scope = "col">Guide Assigned </th>
<th scope = "col">Operation</th>
</thead>
<tbody>
{bookings.map((booking) =>(
<tr>
<th scope = "row">{number++}</th>
<td>{booking.tourId}</td>
<td>{booking.bookingDate}</td>
<td>{booking.arrivalDate}</td>
<td>{booking.country}</td>
{/* {GuideAssigned(booking.guideId)} */}
<td>{guides[booking.tourId]}</td>
<td><Button color="warning" style = {{padding: "5px 5px 5px 5px" , width : "80px" , marginBottom : "8px"}}
onClick = {()=>{
history.push(`/assign-guide/${booking.username}`);
}}
>Assign Guide</Button>
</td>
</tr>
))}
</tbody>
</table>
</div>
<DemoFooter />
</div>
);
}
export default AssignGuide;
Thank you for taking time in going through this! Hope you can help me out with this.
Add a simple if check:
useEffect(()=>{
if(bookings.length === 0){
axios.get("http://localhost:8070/bookings/").then((res) =>{
setBookings(res.data);
})
}
}, [bookings])
Or, making this call on the very first render only:
useEffect(()=>{
axios.get("http://localhost:8070/bookings/").then((res) =>{
setBookings(res.data);
})
}, [])
Without the dependency array, you setBookings on every re-render which causes a re-render itself

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