How to get the pokemon stock dynamically from homepage to detailpage? - reactjs

I'm developing an app that can track pokemon stocks in the store. I fetch the name of data from pokeAPI. Each pokemon is supposed to have its own stock (my pokemon stock is still static) that can be updated in the next page when i click the pokemon's name.
This is the second page:
All in this page is still static. the only dinamic is the pokemons name that I get from params.
How can I update stock of each pokemon and save it? and show it in certain page? Using params (but i think it's not the best practice)? I read I can save the stock to localStorage and accessit later but where should I start from my code?
This is the modal that i will use to update my stock and pass the value to the second page.
first page:
export default function Homepage() {
const [pokemons, setPokemons] = useState([])
const [query, setQuery] = useState("")
const [search, setSearch] = useState("")
let navigate = useNavigate();
const getPokemons = async () => {
try {
let response = await axios.get(`${baseUrl}`)
let pokemons = await response.data.results
setPokemons(pokemons)
} catch (err) {
console.log(err.message)
}
}
const searchPokemon = async (pokemon, e) => {
console.log("masuk seacrh")
try {
if (e.key === 'Enter') {
let response = await axios.get(`${baseUrl} ${pokemon}`)
let data = await response.json()
setSearch(search)
}
} catch (err) {
console.log(err.message)
}
}
useEffect(() => {
getPokemons()
}, [])
// useEffect(() => {
// searchPokemon()
// }, [])
return (
<div className="app-container">
<h1 className="title">Stok Pokémon</h1>
<div className="">
<img src={searchIcon} className="search-icon" />
<input type="text"
className="search-box"
placeholder="Cari Pokémon"
onChange={(e) => setQuery(e.target.value)}
onKeyUp={searchPokemon} />
</div>
<div className="row">
<div className="col">
<Table className="table d-flex row">
<thead>
<tr className="d-flex justify-content-between th-border">
<th scope="col">Nama</th>
<th scope="col" className="d-flex text-right">Stok</th>
</tr>
</thead>
<tbody>
{
pokemons.filter(pokemon => pokemon.name.toLowerCase().includes(query)).map((pokemon, i) => {
console.log(pokemon)
return (
<tr className="d-flex justify-content-between">
<td key={i + 1} className="table-link" onClick={() => {
navigate(`/pokemon/${pokemon.name}`)
}} style={{ textTransform: 'capitalize' }}>{pokemon.name}</td>
<td className="pokemon-stock">10 pcs</td>
</tr>
)
})
}
</tbody>
</Table>
</div>
</div>
</div >
)
}
second page:
function UpdateStockModal(props) {
const [input, setInput] = useState({
pcs: 0,
lusin: 0
})
let navigate = useNavigate();
const [pcs, setPcs] = useState("")
const handleChange = e => {
let newValue = {
...input,
[e.target.name]: e.target.value,
};
setInput(newValue);
};
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="text" name="pcs" value={input.pcs} onChange={handleChange} /> = </Col>
<Col>{input.pcs}</Col>
</Row>
<Row className="modal-table-body">
<Col>Lusin</Col>
<Col className="d-flex align-items-center">12 x <Form.Control name="lusin" className="modal-input lusin" type="text" value={input.lusin} onChange={handleChange} /> = </Col>
<Col>{12 * input.lusin}</Col>
</Row>
<Row className="modal-table-body">
<Col>Total Stok <span>(dalam pcs)</span></Col>
<Col>Lusin</Col>
<Col>{parseInt(12 * input.lusin) + parseInt(input.pcs)}</Col>
</Row>
</Container>
</Modal.Body>
<Modal.Footer>
<Button
variant="primary"
onClick={() => {
navigate(`/update-stock/`)
}} >
Simpan
</Button>
<Button
variant="secondary"
onClick={props.onHide}>
Batal
</Button>
</Modal.Footer>
</Modal>
);
}
export default function PokemonDetail() {
let navigate = useNavigate();
let { name } = useParams()
const [modalShow, setModalShow] = React.useState(false);
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>
<tr className="align-items-center">
<td className="">2 Apr 2021, 08:00</td>
<td className="table-link">Update Stok</td>
<td className="">"Stok Awal"</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>
)
}

Sounds like a shopping cart. I'm assuming you'd like to update the stock for each pokemon. Then on another page, check all the updates before sending an update to the backend. For this I recommend redux saga or rtk query. The state will be globally accessible via the store so you can create your shopping cart securely without using local storage. You can google "redux saga shopping cart" for more examples but these are a couple I've found.
Redux saga
https://github.com/franklsm1/redux-saga-shopping-cart
RTK query
https://codesandbox.io/s/xed9r?file=/README.md

Related

React Draft Wysiwyg always getting Cannot read properties of undefined (reading 'createWithContent') error

My problem is not able render the html code in the editor.
Here is my code for your reference :
const divRef = useRef(null);
const [contentState, setContentState] = useState(); // ContentState JSON
const blocksFromHTML = convertFromHTML(divRef.current.innerHTML);
const state = ContentState.createFromBlockArray(
blocksFromHTML.contentBlocks,
blocksFromHTML.entityMap
);
this.state = {
editorState: EditorState.createWithContent(state)
}
I want to render the table data on the editor. Here is my html code for your reference.
<div className='row' ref={divRef}>
<div className='col-lg-12'>
<table id="checklist">
<tr>
<th>Task List</th>
<th>Assignee</th>
<th>Status</th>
<th>Comments</th>
</tr>
{
ViewChecklistItem.map((row, index) => (
<tr key={row.TaskId}>
<td width="45%">{row.TaskName}</td>
<td>{row.AssigneeName}</td>
<td>
<FormControl sx={{ m: 1, minWidth: 120 }}>
<InputLabel id="demo-controlled-open-select-label">Status</InputLabel>
<Select
className={"copy "+(row.AllowStatusChange === 'Y' ? 'allowed' : 'not-allowed')}
labelId="demo-controlled-open-select-label"
id="demo-controlled-open-select"
open={open[index]}
onClose={() => { handleClose(index) }}
onOpen={() => { handleOpen(index) }}
value={status[index] || row.StatusId}
label="Status"
onChange={(event, newValue) => {
setStatusId(event.target.value);
setTaskId(row.TaskId);
setStatusPopup(true);
}}
>
{StatusList?.map(status => {
return (
<MenuItem value={status.StatusId}>{status.Status}</MenuItem>
);
})}
</Select>
</FormControl>
</td>
<td><a href="javascript:;" onClick={() => viewLogs(row.TaskId, row.TaskName, row.AssigneeName)} className='view-log'><img src={view_log} /> View Log</a></td>
</tr>
))
}
</table>
</div>
</div>
But am getting the output in console.log(divRef.current.innerHTML);
Please help me out. where I missed.
I have upated Editior code below:
<Editor
editorState={editorState}
defaultContentState={contentState}
onContentStateChange={setContentState}
wrapperClassName="wrapper-class"
editorClassName="editor-class"
toolbarClassName="toolbar-class"
/>

How to maintain state and scroll position in React

I'm trying to build a CURD operation component that GET the data from API. When a user clicks on the EDIT, it renders the component showing the details of the line item to be edited. But when the user hits the back button in the browser, the previous component with the post list re-renders and it loses the previous state and scroll position. Is there a way that I can bring the selected row to the first position if I scroll up it displays the previous data and if I scroll down it shows the next coming data?
import React, { useState, useEffect } from "react";
import axios from "axios";
import { Link } from "react-router-dom";
import "bootstrap/dist/css/bootstrap.min.css";
import { CSVLink, CSVDownload } from "react-csv";
import "./Home.css";
const Home = () => {
const [loading, setLoading] = useState(false);
const [users, setUsers] = useState([]);
const [searchTitle, setSearchTitle] = useState("");
const [prime, setPrime] = useState([]);
const [primeid, setPrimeid] = useState("");
const [category, setCategory] = useState([]);
const [categoryid, setCategoryid] = useState("");
const [subcategory, setSubcategory] = useState([]);
const [subcategoryid, setSubcategoryid] = useState("");
const usersList = users.length;
useEffect(() => {
loadUsers();
}, []);
// the below command is used to send the load data from the database
const loadUsers = async () => {
const result = await axios.get(`http://localhost:4000/api/email/`);
// setUsers(result.data);
setUsers(result.data);
// console.log(result)
};
useEffect(() => {
const getprime = async () => {
const resprime = await axios.get(
`http://localhost:4000/api/primewise${primeid}`
);
setPrime(resprime.data.reverse());
};
getprime();
}, []);
const handleprime = (event) => {
const getprimeid = event.target.value;
setPrimeid(getprimeid);
};
useEffect(() => {
const getcategory = async () => {
const rescategory = await axios.get(
"http://localhost:4000/api/categorywise"
);
setCategory(rescategory.data.reverse());
};
getcategory();
}, []);
const handlecategory = (event) => {
const getcategoryid = event.target.value;
setCategoryid(getcategoryid);
};
useEffect(() => {
const getsubcategory = async () => {
const ressubcategory = await axios.get(
"http://localhost:4000/api/subcategorywise"
);
setSubcategory(ressubcategory.data.reverse());
};
getsubcategory();
}, []);
const handleSubcategory = (event) => {
const getSubcategoryid = event.target.value;
setSubcategoryid(getSubcategoryid);
};
useEffect(() => {
if (users.length) {
const scrollPosition = sessionStorage.getItem("scrollPosition");
if (scrollPosition) {
window.scrollTo(0, parseInt(scrollPosition, 10));
sessionStorage.removeItem("scrollPosition");
}
}
}, [users]);
useEffect(() => {
if (users.length) {
const scrollPosition = sessionStorage.getItem("scrollPosition");
if (scrollPosition) {
window.scrollTo(0, parseInt(scrollPosition, 10));
sessionStorage.removeItem("scrollPosition");
}
}
}, [users]);
return (
<div className="App">
<div className="header-1">
<nav className="navbar">
<div className="container-fluid">
<div className="navbar-brand">Supplier Contact Information</div>
{/* <form className="d-flex">
<Link className="btn btn-outline-light" to="/users/statics">
Statics
</Link>
</form> */}
</div>
</nav>
<hr class="solid"></hr>
</div>
<div className="header">
<h4>CATEGORYWISE SUPPLIER INFORMATION</h4>
<div className="col-md-0">
<div class="row">
<div class="col-sm-3">
<div class="card">
<div class="card-body text-center ">
<input
type="text"
placeholder="Power Search..."
className="form-control"
onChange={(e) => setSearchTitle(e.target.value)}
/>
<br />
<select
name="prime"
className="form-control"
onChange={(e) => handleprime(e)}
>
<option value="">--Select Prime--</option>
{prime.map((resprime, index) => (
<option key={index} value={resprime.Prime_Descr}>
{resprime.Prime_Descr}{" "}
</option>
))}
</select>{" "}
</div>
</div>
</div>
<div class="col-sm-3">
<div class="card">
<div class="card-body">
<select
name="category"
className="form-control"
onChange={(e) => handlecategory(e)}
>
<option value="">--Select Category--</option>
{category.map((rescategory, index) => (
<option key={index} value={rescategory.CATEGORY}>
{rescategory.CATEGORY}{" "}
</option>
))}
</select>{" "}
<br />
<select
name="country"
className="form-control"
onChange={(e) => handlecategory(e)}
>
<option value="">--Select Category--</option>
{subcategory.map((ressubcategory, index) => (
<option key={index} value={ressubcategory.SUB_CATEGORY}>
{ressubcategory.SUB_CATEGORY}{" "}
</option>
))}
</select>{" "}
</div>
</div>
</div>
<div class="col-sm-6">
<div class="card-1">
<div class="card-body text-center ">
<CSVLink
filename="supplier contact info."
data={users}
class="btn btn-outline-light"
>
Export to csv
</CSVLink>
<br />
<br />
<div className="container-fluid">
<Link className="btn btn-outline-light" to="/users/add">
Add Supplier
</Link>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div className="outer-wrapper">
<div className="tabel-wrapper">
<table>
<thead>
<th scope="col">S.No</th>
<th scope="col">Prime</th>
<th scope="col">Category</th>
<th scope="col">Sub-Category</th>
<th scope="col">Supplier</th>
<th scope="col">Country</th>
<th scope="col">Region</th>
<th scope="col">Title/Designation</th>
<th scope="col">Representative</th>
<th scope="col">Department</th>
<th scope="col">Primary Contact No</th>
<th scope="col">Secondary Contact No</th>
<th scope="col">EmailId</th>
<th scope="col">Address</th>
<th>Action</th>
</thead>
<tbody>
{/* {usersList ? (
<h4>Loading ...</h4> */}
{loading ? (
<h4>Loading ...</h4>
) : (
users
.filter((value) => {
if (searchTitle === "") {
return value;
} else if (
// (value.PRIME &&
// value.PRIME.toLowerCase().includes(
// searchTitle.toLowerCase()
// )) ||
(value.CATEGORY &&
value.CATEGORY.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.SUB_CATEGORY &&
value.SUB_CATEGORY.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.SUPPLIER &&
value.SUPPLIER.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.COUNTRY &&
value.COUNTRY.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.REGION &&
value.REGION.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.DESIGNATION &&
value.DESIGNATION.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.REPRESENTATIVE_NAME &&
value.REPRESENTATIVE_NAME.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.DIVISION &&
value.DIVISION.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.CONTACT_NO &&
value.CONTACT_NO.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.ALTERNATE_CONTACT_NUMBER &&
value.ALTERNATE_CONTACT_NUMBER.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.EMAIL_ID &&
value.EMAIL_ID.toLowerCase().includes(
searchTitle.toLowerCase()
)) ||
(value.ADDRESS &&
value.ADDRESS.toLowerCase().includes(
searchTitle.toLowerCase()
))
) {
return value;
}
})
.map((user, index) => (
<tr>
<td scope="row">{index + 1}</td>
<td>{user.PRIME}</td>
<td>{user.CATEGORY}</td>
<td>{user.SUB_CATEGORY}</td>
<td>{user.SUPPLIER}</td>
<td>{user.COUNTRY}</td>
<td>{user.REGION}</td>
<td>{user.DESIGNATION}</td>
<td>{user.REPRESENTATIVE_NAME}</td>
<td>{user.DIVISION}</td>
<td>{user.CONTACT_NO}</td>
<td>{user.ALTERNATE_CONTACT_NUMBER}</td>
<td>{user.EMAIL_ID}</td>
<td>{user.ADDRESS}</td>
<td>
<Link
class="btn btn-outline-primary mr-2"
to={`/users/edit/${user.ID}`}
>
Edit
</Link>
</td>
</tr>
))
)}
</tbody>
</table>
</div>
</div>
</div>
);
};
export default Home;

Redux-toolkit: No effect when deleting an item

I have a project and in this project I have several salaries and I am trying to delete a salary, but no action has taken place, and I have no effect on the network,
How can I solve the problem?
I think the error is in the receipt file below
This file contains the delete function of Salary
receipt.js:
import { createSlice, createAsyncThunk } from "#reduxjs/toolkit";
import axios from "axios";
export const getReceipt = createAsyncThunk(
"Receipts/getReceipt",
async (params) => {
console.log("idddd: ", params);
const response = await axios.get(`/financial/receipts/${params}`);
console.log("url: ", "/financial/receipts/", params);
console.log("resss: ", response);
const data = response.data.data;
console.log("reddddd: ", data);
// return data === undefined ? null : data;
return data;
}
);
export const removeDeduction = createAsyncThunk(
"Receipts/removeDeduction",
async (receiptId, id, { dispatch, getState }) => {
console.log("receipt Id: ", receiptId);
console.log("deduction Id: ", id);
const response = await axios.delete(
`/financial/receipts/${receiptId}/deductions/${id}`
);
dispatch(getReceipt());
return response.data;
}
);
export const removeSalary = createAsyncThunk(
"Receipts/removeSalary",
async (receiptId, id, { dispatch, getState }) => {
console.log("receipt Id: ", receiptId);
console.log("deduction Id: ", id);
const response = await axios.delete(
`/financial/receipts/${receiptId}/salaries/${id}`
);
dispatch(getReceipt());
console.log("response delete: ", response.data);
return response.data;
}
);
const receiptSlice = createSlice({
name: "eCommerceApp/receipt",
initialState: null,
reducers: {},
extraReducers: {
[getReceipt.fulfilled]: (state, action) => action.payload,
[removeDeduction.fulfilled]: (state, action) => null,
[removeSalary.fulfilled]: (state, action) => null,
},
});
export default receiptSlice.reducer;
This file contains the entire code, and inside it, the function to delete a salary was called
ReceiptDetails.js:
import Avatar from "#material-ui/core/Avatar";
import Icon from "#material-ui/core/Icon";
import Tooltip from "#material-ui/core/Tooltip";
import Typography from "#material-ui/core/Typography";
import { useState } from "react";
import { useSelector } from "react-redux";
import IconButton from "#material-ui/core/IconButton";
import { removeDeduction, removeSalary } from "../../store/receiptSlice";
import { useDispatch } from "react-redux";
import { Link, useHistory } from "react-router-dom";
function ReceiptDetailsTab() {
const order = useSelector(({ eCommerceApp }) => eCommerceApp.receipt);
const dispatch = useDispatch();
const [map, setMap] = useState("shipping");
const history = useHistory();
function handleRemoveDeduction() {
dispatch(removeDeduction()).then(() => {
history.push("/apps/e-commerce/orders/1");
});
}
function handleRemoveSalary() {
dispatch(removeSalary());
}
return (
<div>
<div className="pb-48">
<div className="pb-16 flex items-center">
<Icon color="action">account_circle</Icon>
<Typography className="h2 mx-12 font-medium" color="textSecondary">
User
</Typography>
</div>
<div className="mb-24">
<div className="table-responsive mb-48">
<table className="simple">
<thead>
<tr>
<th>
<Typography className="font-semibold">Name</Typography>
</th>
<th>
<Typography className="font-semibold">Email</Typography>
</th>
<th>
<Typography className="font-semibold">Phone</Typography>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<div className="flex items-center">
{/* <Avatar src={order.user.avatar} /> */}
<Avatar src="assets/images/avatars/Lily.jpg" />
<Typography className="truncate mx-8">
{/* {`${order.customer.firstName} ${order.customer.lastName}`} */}
Samara Kamal
</Typography>
</div>
</td>
<td>
<Typography className="truncate">
{/* {order.customer.email} */}
samara#gmail.com
</Typography>
</td>
<td>
<Typography className="truncate">
{/* {order.customer.phone} */}
0947483381
</Typography>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div className="pb-48">
<div className="pb-16 flex items-center">
<Icon color="action">attach_money</Icon>
<Typography className="h2 mx-12 font-medium" color="textSecondary">
Salary
</Typography>
</div>
<div className="table-responsive">
<table className="simple">
<thead>
<tr>
<th>
<Typography className="font-semibold">Amount</Typography>
</th>
<th>
<Typography className="font-semibold">
Work Start Date
</Typography>
</th>
<th>
<Typography className="font-semibold">
Work End Date
</Typography>
</th>
<th>
<Typography className="font-semibold">Bonus</Typography>
</th>
</tr>
</thead>
<tbody>
<tr>
<td>
<span>£</span>
<span className="truncate">{order.salary.amount}</span>
</td>
<td>
<span className="truncate">{order.salary.workStartDate}</span>
</td>
<td>
<span className="truncate">{order.salary.workEndDate}</span>
</td>
<td>
<span>£</span>
<span className="truncate">{order.salary.bonus}</span>
</td>
<td>
<IconButton
onClick={handleRemoveSalary}
style={{
color: "red",
border: "none",
marginLeft: "5rem",
}}
>
<Icon>delete</Icon>
</IconButton>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div className="pb-48">
<div className="pb-16 flex items-center">
<Icon color="action">moneyOff</Icon>
<Typography className="h2 mx-12 font-medium" color="textSecondary">
Deductions
</Typography>
</div>
<div className="table-responsive">
<table className="simple">
<thead>
<tr>
<th>
<Typography className="font-semibold">Amount</Typography>
</th>
<th>
<Typography className="font-semibold">Type</Typography>
</th>
<th>
<Typography className="font-semibold">Reason</Typography>
</th>
</tr>
</thead>
<tbody>
{order.deductions.map((deduction) => (
<tr key={deduction.id}>
<td>
<span>£</span>
<span className="truncate">{deduction.amount}</span>
</td>
<td>
<span className="truncate">{deduction.type}</span>
</td>
<td>
<span className="truncate">{deduction.reason}</span>
</td>
<td>
<IconButton
onClick={handleRemoveDeduction}
style={{ color: "red", border: "none" }}
>
<Icon>delete</Icon>
</IconButton>
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
</div>
);
}
export default ReceiptDetailsTab;
Issue
You don't have parameters in the function when you call it
Solve
export const removeDeduction = createAsyncThunk(
"Receipts/removeDeduction",
async (params, { dispatch, getState }) => {
console.log("receipt Id: ", params.receiptId);
console.log("deduction Id: ", params.id);
const response = await axios.delete(
`/financial/receipts/${params.receiptId}/deductions/${params.id}`
);
dispatch(getReceipt());
return response.data;
}
);
function handleRemoveDeduction() {
const params = {
receiptId: '',
id: ''
}
dispatch(removeDeduction(params)).then(() => {
history.push("/apps/e-commerce/orders/1");
});
}

Word is not getting added until the page is refreshed in TableItem component in React

TableItem component added without any data in UI. Could somebody help on this. On refereshing the UI, added data is shown with details in TableItem component.
Table Component Code
import TableItem from "./TableItem";
function Table({ searchWord }) {
const dispatch = useDispatch();
const dictData = useSelector((state) => state.dictionary);
useEffect(() => {
dispatch(getDictionaryAsync());
}, [dispatch]);
return (
<table className="table table-striped">
<thead>
<tr>
<th scope="col">Word</th>
<th scope="col">Description</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{dictData &&
dictData
.filter((e) =>
searchWord === ""
? e
: e.word &&
e.word.toLowerCase().includes(searchWord.toLowerCase())
)
.map((item) => (
<TableItem item={item} key={item.id} searchWord={searchWord} />
))}
</tbody>
</table>
);
}
export default Table;
Below is the TableItem Component Code which i am trying to update,
When i add a word to dictionary it will fetch the details from the server and display it in the React app.
function TableItem({ item }) {
const [modal, setModal] = useState(false);
const openModal = () => {
setModal(true);
};
return (
<>
<tr key={item.id}>
<td style={{ textTransform: "capitalize" }}>{item.word}</td>
<td>
<b style={{ textTransform: "capitalize" }}>
{item.items && item.items[0].category} -{" "}
</b>
{item.items && truncate(item.items[0].definitions[0])}
</td>
<td>
<button className="btn btn-danger btn-sm " onClick={openModal}>
View
</button>
</td>
</tr>
<Modal isOpen={modal} ariaHideApp={true}>
<div className="modal-header">
<h3 className="modal-word-header">
{item.word && item.word.toUpperCase()}
</h3>
<button
className="btn btn-danger btn-sm"
onClick={() => setModal(false)}
>
<i class="fa fa-times" aria-hidden="true"></i>
</button>
</div>
<div className="model-content">
<p>
{item.items &&
item.items.map((e) => {
return (
<>
<i>{e.category}</i>
<ul>
{e.definitions.map((def) => {
return <li>{def}</li>;
})}
</ul>
</>
);
})}
</p>
</div>
</Modal>
</>
);
}
Better add your TableItem component code!
Below code works fine and updated the UI on change in the Data in TableItem,
useEffect(() => {
dispatch(getDictionaryAsync());
}, [dispatch, dictData]); *<--updated code*

SweetAlert2-react Cancel Button does not work

I'm trying to confirm a user delete using Sweetalert2 in react, but when I use the 'Cancel' button, it still sends the form to delete the user, as if I've pressed 'Confirm'. Here's my code
export default function Users() {
const [users, setUsers] = useState([])
const [isModalOpen, setModal] = useState(false)
const [hover, setHover] = useState('')
const [userModal, setuserModal] = useState('')
const [show, setShow] = useState(false)
const [userDelete, setUserDelete] = useState('')
useEffect(() => {
fetch(`${OC_API}/users`)
.then(res => res.json())
.then(res => {
setUsers(res)
console.log(res)
})
.catch(e => console.log(`Hubo un error Cod. 200 ${e}`))
},[])
function toggleModal(user) {
setuserModal(user)
setModal(!isModalOpen)
}
function handleDeleteUser(user) {
fetch(`${OC_API}/userdelete`, {
method: 'POST',
headers: {'Content-Type':'application/json'},
body: JSON.stringify({"user_id": user._id})
}).then(res => {
if (res.ok){
alert('¡Usuario eliminado!')
} else {
alert('¡Hubo un error! Cod. 201')
}
}).then(() => {
fetch(`${OC_API}/users`)
.then(res => res.json(),
error => {alert(`Error de conexión ${error.message}`); throw error;})
.then(data => {
console.log(data)
setUsers(data)
})
.catch(e => console.log(`Hubo un error Cod. 202 ${e}`))
})
}
if (users == undefined || users == [] || users == null ){
return (
<Loading />
)
} else {
return(
<div className="container">
<motion.div className="row justify-content-center"
initial={{ opacity: 0 }}
animate={{ opacity: 1}}
transition={{ duration: 1}}
style={{'paddingTop':'3em'}}
>
<div className="col col-md-12 text-right" >
<AddUserButton />
</div>
<div className="col col-md-12 text-center" >
<ParagraphStyle>
<div className="card" >
<div className="card-header text-left">
Administrar Usuarios
</div>
<div className="card-body">
<div className="table-responsive">
<AdminTableStyle>
<table className="table">
<thead >
<tr>
<th scope="col">Nombre</th>
<th scope="col">RUT</th>
<th scope="col">Correo</th>
<th scope="col">Rol</th>
<th scope="col">Acciones</th>
</tr>
</thead>
<tbody>
{users.map(user => (
<Fragment key={user.id}>
<SweetAlert
show={show}
icon={'warning'}
title="Eliminar Usuario"
text={`¿Desea borrar a usuario ${userDelete.name}?`}
showCancelButton={true}
confirmButtonColor={'#3085d6'}
cancelButtonColor={'#d33'}
cancelButtonText={'Cancelar'}
confirmButtonText={'Confirmar'}
onCancel={ () => {setShow(false)
return }}
onConfirm={() => {
handleDeleteUser(userDelete)
setShow(false)
}}
/>
<tr onMouseOver={() => setHover(user._id)} onMouseLeave={() => setHover('')}>
<td style={{'textAlign': 'left'}}>{user.name}</td>
<td>{user.rut}</td>
<td>{user.email}</td>
<td>{user.role}</td>
<td>
<span style={{'marginRight': '5px'}}>
{
hover==user._id?
<a href="#" onClick={() => toggleModal(user)}>
<FontAwesomeIcon
icon='edit'
/>
</a>
:
''
}
</span>
<span>
{
hover==user._id?
<a href="#" onClick={() => {
setUserDelete(user)
setShow(true)
}}
>
<FontAwesomeIcon
icon='trash'
/>
</a>
:
''
}
</span>
</td>
</tr>
</Fragment>
))}
</tbody>
</table>
</AdminTableStyle>
</div>
</div>
</div>
</ParagraphStyle>
</div>
</motion.div>
<UserEdit
setuserModal={setuserModal}
isModalOpen={isModalOpen}
userModal={userModal}
toggleModal={toggleModal}
/>
</div>
)
}
}
I tried adding an onCancel option in the Sweetalert component and set the Show state to false, but it continues executing the handleDeleteUser function
Any suggestions?

Resources