When add new row in table, old data is beeing like new - reactjs

I create a table, where we can add new row with inputs.
I have 2 components: AddNewRow, which have some inputs for write new data, and TableComponent, which keep data about all rows.
TableComponent:
addRow(rowData){
let newData = this.state.data
console.log(newData)
newData.push(rowData)
console.log(newData)
this.setState({data: newData})
}
render() {
return(
<Table>
<thead>
<tr>
<th>ID</th>
<th>Name</th>
</tr>
</thead>
<tbody>
{this.state.data.map(row =>{
if (row.changeMode){
return(<ChangeRow key={row.id} inputData={row} changeMode={this.changeMode} changeData={this.changeData}/>)
}
else{
return (<TableRow key={row.id} data={row} changeMode={this.changeMode} deleteRow={this.deleteRow}/>)
}
})}
<AddNewRow rowData={{changeMode: false, id: '', name: ''}} addRow={this.addRow}/>
</tbody>
</Table>
)
}
AddNewRow:
export default function AddNewRow({rowData, addRow}){
const [row, setRow] = useState(rowData)
const changeCell = (e, index) =>{
let newRow = row
let key = Object.keys(newRow)[index]
newRow[key] = e.target.value
setRow(newRow)
}
return(
<tr>
{Object.keys(row).map((key, index) => {
if(key != 'changeMode'){
return <td><Input onChange={e => changeCell(e, index)}/></td>
}}
)}
<td><Button color='primary' onClick={() => {
addRow(row)}
}>Add</Button></td>
</tr>
)
}
And when I add a new row, old data is beeing as new.

In the changeCell you're mutating state (changing the same object) something you should avoid when dealing with state. You should make a copy of it.
let newRow = { ...row };

Related

How to delete data from firebase realtime database

I create one table where data get from firebase realtime database. I am adding one delete button on each row in table. Onclick on delete button data should be delete on front end and backend also. But my issue is that when I am click on delete button data is deleted but after refreshing page data get back, data is not deleted from backend. I don't get where I do mistake in code please anyone can help me to solve this issue.
I share my code below.
TableData.js
import React, { Component } from 'react'
import StartFirebase from "../firebaseConfig/index";
import { ref, onValue} from 'firebase/database';
const db = StartFirebase();
export class TableData extends Component {
constructor(props) {
super(props);
this.state = {
tableData: []
}
}
componentDidMount(props) {
const dbRef = ref(db, 'userRecord')
onValue(dbRef, (snapshot) => {
let records = []
snapshot.forEach(childSnapshot => {
let keyName = childSnapshot.key;
let data = childSnapshot.val()
records.push({ "key": keyName, "data": data })
})
this.setState({ tableData: records })
})
}
DeleteData = ({ id, e,props }) => {
fetch(`https://clientsdata-dd45a-default-rtdb.firebaseio.com/userRecord/:${id}.json`,{
method: 'DELETE',
header:{
Accept:"application/json",
"Content-Type":"application/json"
}
}).then((res) => {
res.json().then((resp) => {
window.alert('Are you sure wanted to delete data?: ' + id)
console.log(id) //display id of particule click
const tableData = this.state.tableData.filter((i) => i.id !== id) //if i.id !==id then show
this.setState({ tableData: tableData })
tableData.splice(id, 1)
this.setState({ tableData: tableData })
window.alert("You delete the data successfully!")
console.log(tableData)
})
})
}
render() {
return (
<div>
<table className="table table-bordered table table-hover">
<thead>
<tr>
<th>#</th>
<th scope="col">ID</th>
<th scope="col">Roll</th>
<th scope="col">Name</th>
<th scope="col">Address</th>
<th scope="col">Mobile</th>
</tr>
</thead>
<tbody>
{
this.state.tableData.map((row, id) => {
return (
<tr key={id}>
<th key={id} >{row.key}</th>
<th scope="row">{id+1}</th>
<td>{row.data.userData.RollNum}</td>
<td>{row.data.userData.Name}</td>
<td>{row.data.userData.Address}</td>
<td>{row.data.userData.mobile}</td>
<td>{<button className='btn btn-danger' key={row.id} value={row.data.userData.value} id={row.data.userData.value} onClick={(e) => this.DeleteData({id,e})}>Delete</button>}</td>
</tr>
)
})
}
</tbody>
</table>
</div>
)
}
}
export default TableData

How can I destructure my array of multiple objects

[
0: {_id: '61de38eb6ea1563609e1d0a7', title: 'FALCON SR SUNTOUR', price: '59', description: ' Alloy.., …}
1: {_id: '61d7a8b885c68311be8dd1b3', title: 'Lifelong LLBC2702 Falcon', price: '59', description: 'Low Maintenance: High.., …}
]
I am creating a react project. I have the above array of objects on my database. If any user place order the order list and user email will go into a single array. So my question is how can I display the orders. I have tried a map also tried a nested map but got " order.map is not a function". Here is the code
{orders.map((order, idx) => order.map(singleOrder => console.log(singleOrder)))}
I want to destructure the order details into UI
This is my code:
const ManageAllOrders = () => {
const [orders, setOrders] = useState([])
const { user } = UseAuth()
useEffect(() => {
fetch(`https://polar-savannah-40370.herokuapp.com/dashboard/orders`)
.then(res => res.json())
.then(data => setOrders(data))
}, [user.email])
console.log('orders', orders);
return (
<div>
<h2>Manage Orders</h2>
<Table responsive striped bordered hover size="sm">
<thead>
<tr>
<th>#</th>
<th>Product Name</th>
<th>Price</th>
<th>Email</th>
<th>Address</th>
<th>Order Date</th>
<th>Status</th>
<th>Action</th>
</tr>
</thead>
<tbody>
{
orders?.map((order, idx) =>
Object.defineProperties(order).map(([key, value]) => {
return (
<div>
{key} : {value}
</div>
);
})
)}
{/* {orders.map((order, idx) => order[0].map(console.log()))} */}
</tbody>
</Table>
</div>
);
};
export default ManageAllOrders;
You cannot call map on each order item as it is an object. To iterate over them use Object.entries method.
Try like below
{
orders?.map((order, idx) =>
Object.entries(order).map(
([key, { description, title, price, cartQuantity }]) => {
if (key !== "_id") {
return (
<tr>
<td>{key}</td>
<td>{title}</td>
<td>{price}</td>
<td>{cartQuantity}</td>
<td>{description}</td>
<td>email</td>
<td>address</td>
</tr>
);
}
}
)
);
}
I also noticed your array has stored values with string keys (email, _id). To retrieve them you can do it like below.
{orders?.["email"]}
{orders?.["_id"]}
Code Sandbox
Is Data type Array??
useEffect(() => {
fetch(`https://polar-savannah-40370.herokuapp.com/dashboard/orders`)
.then(res => res.json())
.then(data => setOrders(data))
}, [user.email])

How can I only manipulate only 1 item in the array map independently

I have created a table like this, and I created all of these buttons in the array map function
Whenever I click on the Edit button in every button, it'll display all of it at the same time
How can I press Edit, for example, Edit button on RoleID 1, it'll only display the Edit table there for me to edit, not all of it, I don't know how to separate it since it's stuck in the map array I've created.
Here is my code, I have shorten it for easier to read:
class RoleManagement extends Component {
constructor(props) {
super(props);
this.state = {
roleList: [],
showHideEdit: false,
};
this.toggleEdit = this.toggleEdit.bind(this);
}
async componentDidMount() {
await axios.get("http://localhost:3000/admin/get-role-list").then((res) => {
this.setState({
roleList: res.data,
});
});
}
/---This is the toggle to display edit
toggleEdit(name) {
switch (name) {
case "showHideEdit":
this.setState({ showHideEdit: !this.state.showHideEdit });
break;
default:
null;
}
}
render() {
const { showHideEdit } = this.state;
return (
<table>
<thead>
<tr>
<th>Role ID</th>
<th>Role Name</th>
<th>Action</th>
</tr>
</thead>
{this.state.roleList.map((element, i) => {
return (
<>
<tbody key={i}>
<tr>
<td>{element.role_ID}</td>
<td>{element.rolename}</td>
<td className="admin-button">
/---- The edit button is here
<button
className="admin-config-button"
onClick={() => this.toggleEdit("showHideEdit")}
>
Edit
</button>
{showHideEdit && <RoleEdit id={element.key} />}
</td>
</tr>
</tbody>
</>
);
})}
);
}
}
Because you are using one boolean to check for all RoleEdit. Show when showHideEdit is true, all RoleEdit will show.
To fix, you can update showHideEdit is index of item:
onClick={() => this.toggleEdit(i)}
toggleEdit(i){
if(this.state.showHideEdit === i) {
this.setState({ showHideEdit: null});
} else {
this.setState({ showHideEdit: i});
}
}
{showHideEdit === i && <RoleEdit id={element.key} />}

I have a react table im trying to get it to sort when I click on the this different table Heads

I would assume the issue is coming from signaling portion of the code and the format I have set it in but from all accounts, this should work I know I can break it into an if-else statement but this is the absolute first thing I have created in React and I am trying to use this format. I provided the whole code for the table but the rest is working properly it's just the sorting I am trying to get to work any tips or suggestions would be greatly appreciated. Also if there is anything else in the code you see that I could improve upon as well am open to all suggestions to learn and improve, my search filter is having issues as well but I'm hoping to resolve that.
enter class AppTable extends React.Component {
constructor(props) {
super(props);
this.state = {
users: [],
sorted: '',
directory: 'asc',
compile: [],
};
}
componentDidMount() {
axios.get(`https://randomuser.me/api/?results=20&nat=us`)
.then(res => {
let users = (res && res.data) ? res.data.results: [];
if (!users || users.length === 0){
this.setState({loading: false});
return;
}
const tableList = users.map(state => new User(state));
this.setState({ compile: tableList, users: tableList });
})
}
sorting(sorted) {
const currentField = this.state.sorted;
const users = this.state.users;
let directory = this.state.directory;
if (currentField === sorted) {
directory = directory === 'asc' ? 'desc' : 'asc'
}else{
directory = 'asc'
}
this.signaling(users, sorted,directory);
this.setState({users: users, directory: directory, sorted: sorted})
}
**signaling(objects, field, direction){
const signal = direction === "asc" ? 1 : -1
objects.sort((a,b) => (a[field] > b[field]) ? signal * 1 : ((b[field] > a[field]) ? signal * -1 : 0));
}**
initSearch(evt) {
const searchValue = evt.target.value;
const compile = this.state.compile;
if (!searchValue){
this.setState({users: compile});
return;
}
const filtering = compile.filter((object)=>{
return Object.keys(object).reduce((acc, curr)=>{
return acc || object[curr].toLowerCase().includes(searchValue);
}, false);
});
this.setState({users: filtering});
}
render() {
const throughput = this.state.users;
return <Col>
<Form inline className="mb-2">
<Form.Label className="my-1 mr-2">Search:</Form.Label>
<Form.Control type="text" onChange={event => this.initSearch(event)} placeholder="Search Table" />
</Form>
<Table striped bordered hover>
<thead>
<tr>
<th className="pointer" onClick={() => this.sorting(`${this.firstName}`)}>First Name</th>
<th className="pointer" onClick={() => this.sorting(`${this.lastName}`)}>Last Name</th>
<th className="pointer" onClick={() => this.sorting(`${this.email}`)}>Email</th>
<th className="pointer" onClick={() => this.sorting(`${this.street}`)}>Street</th>
<th className="pointer" onClick={() => this.sorting(`${this.city}`)}>City</th>
<th className="pointer" onClick={() => this.sorting(`${this.state}`)}>State</th>
<th className="pointer" onClick={() => this.sorting(`${this.phone}`)}>Phone</th>
</tr>
</thead>
<tbody>
{throughput.map((individual, index) => (
<AppRow key={index} user={individual}/>
))}
</tbody>
</Table>
</Col>;
}
}
export default AppTable;

not getting any output while mapping an array of objects and displaying table rows in React JS

I have an array of objects and I want to display it's values in a Table
This is how my array looks like:
[{name: 'x', mobile: 'xxx'}, {name: 'y', mobile: 'yyy'}, ......]
I want to display it inside a table.
This is what I tried so far
import React, { Component } from 'react';
import {
Table,
ProgressBar
}
from 'react-bootstrap';
class Display extends Component {
render() {
var records = this.props.googleData;
const API = this.props.api;
const placeURI = this.props.placeURI;
var rows = [];
for(let p_id of records.results){
let dataURI = `${placeURI}${p_id.place_id}${API}`;
let proxyUrl = 'https://cors-anywhere.herokuapp.com/',
targetUrl = dataURI
fetch(proxyUrl + targetUrl)
.then((res) => res.json())
.then((data) => {
let jsonData = JSON.parse(JSON.stringify(data));
//console.log(jsonData);
rows.push(jsonData.result);
})
.catch((e)=> console.log(`Error! ${e.message}`));
}
console.log(rows);
return (
<div>
<ProgressBar now={45} />
<Table striped bordered condensed hover responsive>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Full Address</th>
<th>Phone Number</th>
<th>International P.no</th>
<th>Website</th>
<th>Rating</th>
</tr>
</thead>
<tbody>
{rows.map(( listValue, index ) => {
return (
<tr key={index}>
<td>{listValue.name}</td>
<td>{listValue.title}</td>
<td>{listValue.price}</td>
</tr>
);
})}
</tbody>
</Table>
</div>
);
}
}
export default Display;
This is how my array looks
But the map() is not returning any row. And if there is any suggestion by which I can improve my code is extremely appreciable. Please help
import React, { Component } from 'react';
import {
Table,
ProgressBar
}
from 'react-bootstrap';
class Display extends Component {
constructor(props) {
super(props);
this.state={
rows: []
}
}
componentDidMount = () => {
var records = this.props.googleData;
const API = this.props.api;
const placeURI = this.props.placeURI;
var rows = [];
for (let p_id of records.results) {
let dataURI = `${placeURI}${p_id.place_id}${API}`;
let proxyUrl = 'https://cors-anywhere.herokuapp.com/',
targetUrl = dataURI
fetch(proxyUrl + targetUrl)
.then((res) => res.json())
.then((data) => {
let jsonData = JSON.parse(JSON.stringify(data));
//console.log(jsonData);
rows.push(jsonData.result);
})
.catch((e) => console.log(`Error! ${e.message}`));
}
this.setState({
rows:rows
})
console.log(rows);
};
render() {
return (
<div>
<ProgressBar now={45} />
<Table striped bordered condensed hover responsive>
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Full Address</th>
<th>Phone Number</th>
<th>International P.no</th>
<th>Website</th>
<th>Rating</th>
</tr>
</thead>
<tbody>
{this.state.rows.map(( listValue, index ) => {
return (
<tr key={index}>
<td>{listValue.name}</td>
<td>{listValue.title}</td>
<td>{listValue.price}</td>
</tr>
);
})}
</tbody>
</Table>
</div>
);
}
}
export default Display;

Resources