delete mutation is executed before modal is shown - javascript

Description
i'm working on reactjs and apollo client project. i'm also developing deleteUser feature. delete mutation is working but without modal confirmation. i want to add modal confirm when admin click delete button. it means, delete mutation is executed after admin click on button yes inside modals.
Problem
When i'm clicking delete user button, mutation delete is executed first than modal is show. and when i'm click "yes" button, it'll be refetching data.
Here's the code :
import React, { useState, useEffect } from "react";
import { Table, Button } from "react-bootstrap";
import { useMutation } from "#apollo/client";
import { GET_ALL_USERS } from "../../../gql/query";
import { DELETE_USER } from "../../../gql/mutation";
import ModalEdit from "../Modals/ModalEdit";
import ModalConfirm from "../../Common/Modals/ModalConfirm";
const TableUserInfo = ({ data, variables }) => {
const [showModal, setShowModal] = useState(false);
const [username, setUsername] = useState("");
const [isDeleting, setIsDeleting] = useState(false);
const handleShowModal = () => setShowModal(true);
const handleCloseModal = () => setShowModal(false);
const [deleteUser, { error, loading, refetch }] = useMutation(DELETE_USER);
if (loading) return <p>Loading...</p>;
if (error) return <p>Error</p>;
if (
!data ||
!data.getAllUsers ||
!data.getAllUsers.rows ||
!data.getAllUsers.rows.length
) {
return <p className="text-center"> Tidak ada data tersedia </p>;
}
// delete user handler
const handleDelete = (userToDelete) => {
setIsDeleting( true );
deleteUser({
variables: { username: userToDelete },
update(cache, { data }) {
const { getAllUsers } = cache.readQuery({
query: GET_ALL_USERS,
variables,
});
cache.writeQuery({
query: GET_ALL_USERS,
variables,
data: {
getAllUsers: {
...getAllUsers,
totalItems: getAllUsers.totalItems - 1,
rows: getAllUsers.rows.filter((user) => user.username !== userToDelete)
}
}
});
},
onError: (error) => {
console.log(JSON.stringify(error, null, 2));
},
});
}
return (
<Table responsive>
<thead>
<tr>
<th>No</th>
<th>Nama Pengguna</th>
<th>Role Akun</th>
<th>Email</th>
<th>Tanggal Daftar</th>
<th>Status Akun</th>
<th>Pengaturan</th>
</tr>
</thead>
<tbody>
{data.getAllUsers.rows.map((user, index) => (
<tr key={user.username}>
<td>{index + 1}</td>
<td>{user.full_name}</td>
<td>{user.group_id}</td>
<td>{user.email}</td>
<td>{user.created_dtm}</td>
<td>{user.status}</td>
<td>
{user.status !== "ACTIVE"
? [
<Button
key="Aktifkan Akun"
className="d-block mb-2 text-white bg-secondary w-100"
>
Aktifkan Akun
</Button>,
<Button
key="Ganti Role Akun"
className="d-block mb-2 btn-block btn-sm w-100"
disabled
>
Ganti Role Akun
</Button>,
]
: user.group_id === "admin"
? [
<Button
key="Ganti Role Akun"
variant="outline-success"
className="d-block btn-sm mb-2 w-100"
>
Ganti Role Akun
</Button>,
]
: [
<Button
key="Pilih Role Akun"
className="d-block btn-sm mb-2 w-100"
>
Pilih Role Akun
</Button>,
]}
<Button
key="Edit"
variant="outline-primary"
onClick={() => {
setShowModal(true);
setUsername(user.username);
}}
className="d-block btn-block btn-sm mb-2 w-100"
>
Edit
</Button>
<Button
key="Hapus"
variant="outline-danger"
onClick={() => {
handleDelete(user.username)}
}
disabled={loading}
className="d-block btn-block btn-sm mb-2 w-100"
>
Hapus
</Button>
</td>
</tr>
))}
</tbody>
{showModal ? (
<ModalEdit
show={handleShowModal}
onClose={handleCloseModal}
username={username}
/>
) : isDeleting ? ( <ModalConfirm
show={ isDeleting }
onHide= { () => { handleCloseModal(); setIsDeleting(false); } }
handleDelete={ handleDelete }
userToDelete={ username } />
) : null}
</Table>
);
};
export default TableUserInfo;
Question
How to fix the error and make data user is delete when admin click "yes" in modals ?
any help will be appreciated, thankyou.

Related

How to add up two numbers gotten from firebase with react

Am new to React, and it feels like its very difficult to carry out mathematical calculations with react, Have been trying to add up two values gotten from firebase database but it keeps displaying the values as string and not adding the two values, Please I need help.
{contactObjects[id].gcc} + {contactObjects[id].lcc}
adding this two will only display all as string
E.g
if {contactObjects[id].gcc} is = 10 in firebase datebase and {contactObjects[id].lcc} as = 30
And adding + to the code wont sum up the two values, it will only display them as
10 + 30 which is in string and not 40
Please how can i go about it.
import React, { useState, useEffect } from "react";
import ContactForm from "./ContactForm";
import firebaseDb from "../firebase";
const Contacts = () => {
var [contactObjects, setContactObjects] = useState({});
var [currentId, setCurrentId] = useState("");
useEffect(() => {
firebaseDb.child("contacts").on("value", (snapshot) => {
if (snapshot.val() != null)
setContactObjects({
...snapshot.val(),
});
else setContactObjects({});
});
}, []); // similar to componentDidMount
const addOrEdit = (obj) => {
if (currentId == "")
firebaseDb.child("contacts").push(obj, (err) => {
if (err) console.log(err);
else setCurrentId("");
});
else
firebaseDb.child(`contacts/${currentId}`).set(obj, (err) => {
if (err) console.log(err);
else setCurrentId("");
});
};
const onDelete = (key) => {
if (window.confirm("Are you sure to delete this record?")) {
debugger;
firebaseDb.child(`contacts/${key}`).remove((err) => {
if (err) console.log(err);
else setCurrentId("");
});
}
};
return (
<>
<div className="jumbotron jumbotron-fluid">
<div className="container">
<h1 className="display-4 text-center">Contact Register</h1>
</div>
</div>
<div className="row">
<div className="col-md-5">
<ContactForm {...{ addOrEdit, currentId, contactObjects }} />
</div>
<div className="col-md-7">
<table className="table table-borderless table-stripped">
<thead className="thead-light">
<tr>
<th>Full Name</th>
<th>Mobile</th>
<th>Email</th>
<th>Address</th>
<th>Street</th>
<th>Address</th>
<th>Gcc</th>
<th>Lcc</th>
</tr>
</thead>
<tbody>
{Object.keys(contactObjects).map((id) => {
return (
<tr key={id}>
<td>{contactObjects[id].fullName}</td>
<td>{contactObjects[id].mobile}</td>
<td>{contactObjects[id].email}</td>
<td>{contactObjects[id].address}</td>
<td>{contactObjects[id].street}</td>
<td>{contactObjects[id].gcc}</td>
<td>{contactObjects[id].lcc}</td>
<td>
{contactObjects[id].gcc} +
{contactObjects[id].lcc}
</td>
<td>
<a
className="btn text-primary"
onClick={() => {
setCurrentId(id);
}}
>
<i className="fas fa-pencil-alt"></i>
</a>
<a
className="btn text-danger"
onClick={() => {
onDelete(id);
}}
>
<i className="far fa-trash-alt"></i>
</a>
</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
</>
);
};
export default Contacts;
If I understand correctly, then just parse these values to int. If in DB these are 'string'
{parseInt(contactObjects[id].gcc) + parseInt(contactObjects[id].lcc)}

How to dynamically create an array of table in ReactJS?

I want to make my table row dynamic so it can automatically add new data from the MySQL database but I don't know how. Can you help me?
Here is my static data that I wanted to make dynamic.
const data = {
rows: [
{
Campus_name: 'National Arabella SHS',
tel_number: ' 123-12-123',
action:
<div className='action-icon-container'>
<Tooltip title="Edit" trigger="hover">
<Link to='/admin/campus/edit-campus/:id' state={{bc_edit_type : 1}}><MdEdit className='action-icon edit' /></Link>
</Tooltip>
</div>
},
{
Campus_name: 'College of Arabella - Main',
tel_number: ' 123-12-123',
action:
<div className='action-icon-container'>
<Tooltip title="Edit" trigger="hover">
<MdEdit className='action-icon edit' />
</Tooltip>
</div>
},
{
Campus_name: 'College of Arabella Extension',
tel_number: ' 123-12-123',
action:
<div className='action-icon-container'>
<Tooltip title="Edit" trigger="hover">
<MdEdit className='action-icon edit' />
</Tooltip>
</div>
},
]
};
Here is the part where I get the data from the database and store it in 'campusValues' variable.
const CampusPage = () => {
const [campusValues, setCampusValues] = useState([]);
const GetCampusValues = () => {
Axios.get("http://localhost:5000/campusValues").then((response) => {
console.log(response);
setCampusValues(response.data);
});
}
useEffect(() => {
let ignore = false;
if (!ignore)
GetCampusValues();
return () => { ignore = true; }
},[]);
return (...);
}
export default CampusPage
To make a dynamic table just map the table rows:
<table>
<tr>
<th>...</th>
<th>...</th>
<th>...</th>
</tr>
{
campusValues.map(value => (
<tr key={...}>
<td>{value.id}</td>
<td>{value.name}</td>
<td>...</td>
</tr>
))
}
</table>

My search bar React does not return any results

I've added a search bar to my React-Firebase Dashboard.As a result, the search bar is displayed with the table of clients stored in Cloud Firestore, when I enter a text in the search bar It returns an empty table even if that word exists in the table.
PS: Both of the Results are shown below in screenshots
The table initially rendered
table after writing anything in the search bar
Customer.js
import React, { Fragment, useState } from "react";
import { Avatar } from '#material-ui/core';
import PageTitle from "../../../../layouts/PageTitle";
import { Dropdown, Table } from "react-bootstrap";
import { fire } from "../../../../../fire";
import { firestore } from "../../../../../fire";
import { collection, query, where } from "../../../../../fire";
import App from "../../../../../App";
export default class Recipe extends React.Component {
state = {
searchTerm : "",
Users: []
}
constructor(props){
super(props);
}
searchByTerm = (value) => {
this.setState({searchTerm : value});
}
componentDidMount() {
firestore.collection("Users").get().then((querySnapshot) => {
let User = []
querySnapshot.forEach((doc) => {
console.log(`${doc.id} => ${doc.data().lastn}`);
User.push({
id : doc.id,
data: doc.data()})
});
this.setState({Users : User})
});
}
delete = (id) => {
console.log(id)
firestore.collection("Users").doc(id).delete().then(() => {
console.log("Document successfully deleted!");
this.props.history.push("#")
}).catch((error) => {console.error("Error removing document: ",
error);
});
}
render() {
return (
<Fragment>
<div className="col-12">
<div className="card">
<div className="card-header">
<div className="input-group search-area d-lg-inline-flex d-none mr-
5">
<input
type="text"
className="form-control"
placeholder="Search here"
onChange ={(e) => {
this.searchByTerm(e.target.value);
}}
/>
<div className="input-group-append">
<span className="input-group-text"
>
<svg
width={20}
height={20}
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M23.7871 22.7761L17.9548 16.9437C19.5193 15.145 20.4665 12.7982 20.4665 10.2333C20.4665 4.58714 15.8741 0 10.2333 0C4.58714 0 0 4.59246 0 10.2333C0 15.8741 4.59246 20.4665 10.2333 20.4665C12.7982 20.4665 15.145 19.5193 16.9437 17.9548L22.7761 23.7871C22.9144 23.9255 23.1007 24 23.2816 24C23.4625 24 23.6488 23.9308 23.7871 23.7871C24.0639 23.5104 24.0639 23.0528 23.7871 22.7761ZM1.43149 10.2333C1.43149 5.38004 5.38004 1.43681 10.2279 1.43681C15.0812 1.43681 19.0244 5.38537 19.0244 10.2333C19.0244 15.0812 15.0812 19.035 10.2279 19.035C5.38004 19.035 1.43149 15.0865 1.43149 10.2333Z"
fill="#A4A4A4"
/>
</svg>
</span>
</div> </div>
<h4 className="card-title">Customer List </h4>
</div>
<div className="card-body">
<Table responsive className="w-100">
<div id="example_wrapper" className="dataTables_wrapper">
<table id="example" className="display w-100 dataTable">
<thead>
<tr role="row">
<th>Avatar</th>
<th>Email</th>
<th>Firstname</th>
<th>Lastname</th>
<th>PhoneNumber</th>
{/* <th className="pl-5 width200">
Billing Address
</th> */}
<th>Action</th>
</tr>
</thead>
<tbody>
{this.state.Users.filter( (val) =>{
const { email = "", firstname = "" } = val;
// console.log(this.state.searchTerm);
if (this.state.searchTerm === "") {
return val;
} else if (
email.toLowerCase().includes(this.state.searchTerm.toLowerCase()) ||
firstname.toLowerCase().includes(this.state.searchTerm.toLowerCase())
) {
return val;
}
}).map(data => {
return (
<tr>
<td> <Avatar className ="rounded-circle img-fluid" src={data.data.avatar}/> </td>
<td>{data.data.email}</td>
<td>{data.data.firstname}</td>
<td>{data.data.datalastname}</td>
<td>{data.data.phonenumber}</td>
<td>
<div
className="btn btn-danger shadow btn-xs sharp" onClick ={this.delete.bind(this, data.id)}
>
<i className="fa fa-trash"></i> </div></td>
</tr>
);
})}
</tbody>
</table>
</div>
</Table>
</div>
</div>
</div>
</Fragment>
);
};
};
Array.prototype.filter callback should be returning a boolean, not the element being iterated over.
This is how I suggest rewriting your filter function: if there is no search term (i.e. falsey) then return true to indicate all elements iterated over should be return, otherwise, return the result of the comparison.
const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();
...
Users.filter((val) => {
const { data: { email = "", firstname = "" } = {} } = val;
if (term) {
return (
email.toLowerCase().includes(term) ||
firstname.toLowerCase().includes(term)
);
}
return true;
})
A slightly more succinct version could be written as follows:
const { Users, searchTerm } = this.state;
const term = this.state.searchTerm.toLowerCase();
...
Users.filter(({ data: { email = "", firstname = "" } = {} }) =>
term ? email.concat(firstname).toLowerCase().includes(term) : true
)
Update
After you've stated that you implemented my suggestions and it's still not working I took a closer look at what you are rendering and noticed that in the .map callback you reference each field (email, firstname, etc...) from a data property on each element. Since it seems you are able to render your data when no filter is being applied I'll assume this structure to be correct. As such then, the .filter callback needs to also reference the nested field properties from a data property. I've updated the above code snippets.

Duplicate value of useRef current value after switching between tabs in react

If i switch between Transfer to Beneficiary and All Beneficiary tab the Select options get duplicated but if i change the second useEffect hook dependency to allBeneficiary.current instead of beneficiaries presently there, Select options doesnt duplicate, but the options are not rendered on the first render until I switch to All Beneficiary tab and back to Transfer Beneficiary
Below is the Transfer to Beneficiary code
// Hooks and Contexts
import React, { useState, useContext, useEffect, useRef } from "react";
import { TransferPointsContext } from "../../../../../context/TransferPoints";
import { LoaderContext } from "../../../../../context/Loading";
// Components
import TransferSummary from "../../../../common/modals/TransferSummary";
import Loading from "../../../../features/Loader/Loading";
// UI
import swal from "sweetalert";
import toastr from "toastr";
import Select from "react-select";
import "./css/transfer-points.css";
import { nanoid }from 'nanoid'
function TransferPoints() {
const [showTransferSummary, setShowTransferSummary] = useState(false);
const [transferSummaryData, setTransferSummaryData] = useState(false);
const [showBeneficiaryDataPage, setShowBeneficiaryDataPage] = useState(false);
const [checked, setChecked] = useState(false);
const [ options, setOptions ] = useState([])
const {
verifyCardNumber,
verifyCardState,
getBeneficiaryList,
beneficiaries, //list of beneficiaries from API
hideBeneficiaryDataPage,
setInputs,
inputs,
} = useContext(TransferPointsContext);
const { loading } = useContext(LoaderContext);
toastr.options.progressBar = true;
toastr.options = {
toastClass: "alert",
iconClasses: {
error: "alert-error",
info: "alert-info",
success: "alert-success",
warning: "alert-warning",
},
};
const allBeneficiaries = useRef([]);
useEffect(() => {
getBeneficiaryList();
}, [allBeneficiaries]);
useEffect(() => {
if (beneficiaries.data !== null) {
if (
beneficiaries.data.status === 0 &&
beneficiaries.data.success === false
) {
toastr.error("Failed to fetch user beneficiaries!", "error", {
iconClass: "toast-error",
});
console.log("beneficiaries", beneficiaries.data);
} else if (
beneficiaries.data.status === 1 &&
beneficiaries.data.success === true
) {
console.log('All beneficiary ', allBeneficiaries.current)
beneficiaries.data.data.forEach((beneficiary) => {
console.log('For each ', beneficiary)
allBeneficiaries.current.unshift({
value: beneficiary.membership_number,
label: `${beneficiary.first_name} ${beneficiary.last_name == null ? '' : beneficiary.last_name}`,
});
});
console.log('LENGTH ', allBeneficiaries.current.length)
}
}
}, [beneficiaries]);
useEffect(() => {
if (hideBeneficiaryDataPage) {
setShowBeneficiaryDataPage(false);
}
}, [hideBeneficiaryDataPage]);
const beneficiaryData = useRef({});
useEffect(() => {
if (verifyCardState.data !== null) {
if (
verifyCardState.data.status === 1 &&
verifyCardState.data.success === true
) {
setShowBeneficiaryDataPage(true);
beneficiaryData.current = {
name: `${verifyCardState.data.data.first_name} ${verifyCardState.data.data.last_name == null ? '' : verifyCardState.data.data.last_name}`,
};
toastr.success("Membership Id Validated!", "Success", {
iconClass: "toast-success",
});
return;
}
if (
verifyCardState.data.status === 0 &&
verifyCardState.data.success === false
) {
if (verifyCardState.data.message && !verifyCardState.data.data) {
toastr.error(verifyCardState.data.message, "Validation failed!", {
iconClass: "toast-error",
});
setShowBeneficiaryDataPage(false);
return;
}
setShowBeneficiaryDataPage(false);
const errorMessages = verifyCardState.data.data;
for (const error in errorMessages) {
toastr.error(errorMessages[error], "Validation Error!", {
iconClass: "toast-error",
});
}
return;
}
}
}, [verifyCardState]);
const handleSearchInput = (event) => {
const card_number = event.value;
setInputs((inputs) => ({
...inputs,
card_number,
}));
verifyCardNumber(card_number);
};
const proceedToTransfer = () => {
const amount = document.getElementById("amount").value;
if (amount.trim().length === 0) {
swal({
title: "Oops!",
text: `Amount field cannot be empty`,
icon: "error",
button: "Ok",
});
return;
}
setShowTransferSummary(!showTransferSummary);
setTransferSummaryData({
amount,
name: beneficiaryData.current.name,
membership_id: inputs.card_number,
save_beneficiary: (beneficiaryData.current.save_beneficiary == 1) ? 1 : 0,
});
};
const handleInputChange = (event) => {
event.persist();
setInputs((inputs) => ({
...inputs,
[event.target.name]: event.target.value,
}));
};
const handleChange = (event) => {
event.persist();
setChecked(event.target.checked);
const save_beneficiary = event.target.checked === true ? 1 : 0;
beneficiaryData.current.save_beneficiary = save_beneficiary;
};
console.log('LENGTH ', allBeneficiaries.current)
// console.log('current beneficiaries ', (allBeneficiaries.current) )
// console.log('CHECKED ', beneficiaryData.current.save_beneficiary )
// let id = nanoid()
return (
<div>
{/* {loading ? <Loading /> : ""} */}
<form action="#">
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label htmlFor="acc-email">Select Beneficiary </label>
<Select
onChange={handleSearchInput}
className="basic-single"
classNamePrefix="select"
isClearable="true"
isSearchable="true"
name="beneficiary_card_number"
defaultValue="Select"
options={allBeneficiaries.current} //THIS RETURNS DUPLICATED VALUE ON NAVIGATING TO ALL BENEFICIARIES AND BACK
/>
</div>
<h6 class="mt-3 heading-border border-0">OR</h6>
<div className="row align-items-center justify-content-between">
<div className="col-md-8">
<label htmlFor="card_number">Enter Membership Id</label>
<input
type="text"
className="form-control"
name="card_number"
onChange={handleInputChange}
value={inputs.card_number}
/>
</div>
<div className=" col-4 " style={{marginTop: '30px', paddingLeft: '10px', textAlign: 'end',}}>
<button
onClick={() => verifyCardNumber(inputs.card_number)}
type="button"
className="btn-lg btn btn-primary"
>
Validate Id
</button>
</div>
</div>
</div>
{showBeneficiaryDataPage === true ? (
<div className="col-sm-12">
<h6 class="mt-3 heading-border border-0"></h6>
<div className="row">
<div className="col-md-6">
<div className="form-group">
<label htmlFor="acc-name">Name</label>
<input
type="text"
className="form-control"
id="acc-name"
required
disabled
name="acc-name"
value={beneficiaryData.current.name}
/>
</div>
</div>
<div className="col-md-6">
<div className="form-group">
<label htmlFor="acc-lastname">Membership Id</label>
<input
type="text"
className="form-control"
id="acc-lastname"
required
disabled
name="acc-lastname"
value={inputs.card_number}
/>
</div>
</div>
</div>
<div className="row">
<div className="col-md-12">
<div className="form-group">
<label htmlFor="acc-lastname">Amount</label>
<input
type="text"
className="form-control"
id="amount"
required
name="amount"
onChange={handleInputChange}
value={inputs.amount}
/>
</div>
</div>
</div>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
checked={checked}
name="save_beneficiary"
onChange={handleChange}
/>
<span className="ml-3 font-weight-bold terms-condition">
Save Beneficiary
</span>
</div>
<div className="mb-2"></div>
<div className="form-footer">
<div className="col-md-12 d-flex justify-content-center">
<button
onClick={() => proceedToTransfer()}
type="button"
className="btn-lg w-50 btn btn-primary"
>
Proceed
</button>
</div>
</div>
</div>
) : (
""
)}
</div>
</form>
{showTransferSummary === true ? (
<TransferSummary data={transferSummaryData} setShowTransferSummary={setShowTransferSummary} setShowBeneficiaryDataPage={setShowBeneficiaryDataPage}/>
) : (
""
)}
</div>
);
}
export default React.memo(TransferPoints);
This is the code for All Beneficiaries
import React, { useState, useContext, useEffect, useRef } from "react";
import "./css/transfer-points.css";
import { TransferPointsContext } from "../../../../../context/TransferPoints";
import Loading from "../../../../features/Loader/Loading";
import swal from "sweetalert";
import { LoaderContext } from "../../../../../context/Loading";
import toastr from "toastr";
import axios from 'axios'
import { ToastContainer, toast } from 'react-toastify';
function ShowAllBeneficiariesPage() {
const [ data, setData ] = useState([])
const {
getBeneficiaryList,
beneficiaries,
removeBeneficiary,
state,
} = useContext(TransferPointsContext);
const { loading } = useContext(LoaderContext);
toastr.options.progressBar = true;
toastr.options = {
toastClass: "alert",
iconClasses: {
error: "alert-error",
info: "alert-info",
success: "alert-success",
warning: "alert-warning",
},
};
const handleDelete = (id) => {
swal({
title: "Are you sure you want to remove beneficiary?",
text: "You won't be able to revert this!",
icon: "warning",
buttons: ["Cancel", "Proceed!"],
showCancelButton: true,
confirmButtonColor: "#3085d6",
cancelButtonColor: "#d33",
}).then((result) => {
if (result === true) {
removeBeneficiary(id);
console.log('ID OF RECEIVER ', id)
const newBeneficiary = data.filter(add => add.id !== id)
setData(newBeneficiary)
toastr.success("Beneficiary Removed !", "Success", {
iconClass: "toast-success",
});
}
});
};
const fetchData = () => {
axios.get(`user/beneficiaries`)
.then( res => setData(res.data.data ))
}
useEffect(() => {
fetchData()
}, [])
return (
<div>
{/* {loading ? <Loading /> : ""} */}
{ data.length === 0 ?
(
<div style={{textAlign: 'center'}}>No beneficiaries found</div>
)
:
(
<div className="col-sm-12">
{data.map((item) => {
console.log('Beneficiary Data ', data)
return (
<p className="mb-1 p-4 beneficiary-list">
{item.first_name} {item.last_name} - {item.membership_number}
<i
style={{ cursor: "pointer" }}
onClick={() => handleDelete(item.id)}
class="float-right fas fa-trash"
></i>{" "}
</p>
);
})}
</div>
)}
</div>
);
}
export default (ShowAllBeneficiariesPage);
I can't completely fix your issue, because I'd need more context and time, but I've found some issues on your code.
Never ever ever, have something in your render code that has a reference to a useRef variable. When a useRef value changes, react will completely ignore it and will not update your component. Use setState for those.
It sounds like your allBeneficiaries instead of being a ref or a state it's just derived state: It looks like it's a derived value from beneficiaries. In this case, you don't need to use any hook, just declare it as a const (e.g. const allBeneficiaries = getBeneficiaries(beneficiaries)). If you have performance issues, then consider using useMemo, but it should not be needed.
Never use a useRef as a dependency value in a useEffect - Same thing, react doesn't care about ref values, so you'll have unexpected behaviour there (effects retriggering when it shouldn't, effects not triggering when they should)
Try to avoid useEffect as much as posible. It should only be used for specific cases, such as fetching something from a server or manipulating the dom. For the rest of them, it's just problematic, best avoided.
Using allBeneficiaries (or any other ref object) as a dependency for a hook won't help you at all. The ref object's identity will never change over the lifetime of a component.
If you want to run an effect/... when the value boxed within the allBeneficiaries ref changes, the dependency will need to be allBeneficiaries.current.
Beside that, there's no good reason to use a ref for allBeneficiaries. Since it affects rendering, you will want to save it as a state atom (useState).

mdbreact is showing an unexpected behaviour

I am using mdbreact package to make table for my data. It's having an action button in the last column which opens a modal for editing the data.
Scenario is
I loaded the table with initial data
And then applied some sorting on it
And now I click on the edit button to open the modal for editing the data
Now the sorting gets automatically removed and it's looking really weird that modal is opening and data is changing in the background.
What do I need ?
I don't want data to be changed on the backend. Also, I don't know how to store that sorted data in the state even as I am using mdbreact for the first time.
Here you can check the exact issue I am facing.
File where I am formatting data and adding event and action to each row:
import React from 'react'
import PayRatesTable from './PayRatesTable'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faPencilAlt, faAngleRight, faAngleLeft } from '#fortawesome/free-solid-svg-icons'
import { Button, Row, Col } from 'reactstrap'
const columns =
[
{
label: 'Certificate',
field: 'certificate',
sort: 'asc'
},
{
label: 'Speciality',
field: 'speciality',
sort: 'asc'
},
{
label: 'Pay Rate ($)',
field: 'pay_rate',
sort: 'disabled'
},
{
label: 'Weekend Pay Rate ($)',
field: 'weekend_pay_rate',
sort: 'disabled'
},
{
label: 'Action',
field: 'action',
sort: 'disabled'
}
]
const formatCertSpec = (data, certificates, handleModelClose) => {
var cert = []
data && data.map((item) => (
certificates && certificates.map((certs) => {
if (certs.id == item.certificateId) {
certs.specialities && certs.specialities.map((certSpec) => {
if (item.speciality == certSpec.id) {
cert.push({
certificate: certs.abbreviation,
speciality: certSpec.name,
pay_rate: item.payRateCents ? `$${(item.payRateCents / 100).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}` : '',
weekend_pay_rate: item.weekendPayRateCents ? `$${(item.weekendPayRateCents / 100).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}` : '',
action: <Button color="link" onClick={(event) => {
event.preventDefault()
handleModelClose({
certificate: certs.abbreviation,
speciality: certSpec.name,
id: item.id,
pay_rate: item.payRateCents / 100,
weekend_pay_rate: item.weekendPayRateCents / 100,
})}}>
<FontAwesomeIcon key="edit" className="ml-2" icon={faPencilAlt} />
</Button>
})
}
})
}
})
))
return cert
}
function AddPayRatesComp({
data,
certificates,
handleModelClose,
handleNextPrevTabs
}) {
const certAndSpecPayData = formatCertSpec(data, certificates, handleModelClose)
console.log(certAndSpecPayData)
return (
<div className="container-fluid">
<PayRatesTable
columns={columns}
certificates={certificates}
certs={certAndSpecPayData}
/>
<Row className="mb-2 text-center">
<Col className="col-md-3">
</Col>
<Button
type="button"
onClick={() => handleNextPrevTabs('prev')}
outline
color="secondary"
className="btn-rounded font-weight-bold py-1 mr-2 mt-2 col-sm-12 col-md-3"
><FontAwesomeIcon icon={faAngleLeft} /> Previous</Button>
<Button
type="button"
onClick={() => handleNextPrevTabs('next')}
outline
color="secondary"
disabled
className="btn-rounded font-weight-bold py-1 mr-2 mt-2 col-sm-12 col-md-3"
>Next <FontAwesomeIcon icon={faAngleRight} /></Button>
</Row>
</div>
);
}
export default AddPayRatesComp;
PayRatesTable.js
import React from 'react'
import { MDBDataTable } from 'mdbreact'
const PayRatesTable = ({ columns, certs }) => {
const data = {
columns: columns,
rows: certs
}
return (
<>
<MDBDataTable
striped
bordered
medium="true"
responsive
data={data}
order={['certificate', 'asc' ]}
/>
<style jsx global>{`
#import "../styles/bootstrap-custom/jsx-import";
.table thead:last-child{
display:none;
}
`}</style>
</>
);
}
export default PayRatesTable;
This is all that I can provide due to security issues.

Categories