Not able to Received the id in onKeydown in react - reactjs

code:-
useEffect(() => {
setPlayer();
window.addEventListener("keydown", handleKeyDown);
return function cleanup() {
window.removeEventListener("keydown", handleKeyDown);
};
}, [props])
const handleKeyDown = (event, ID) => {
if (event.key === "Delete") {
//alert(name);
axios({
method: 'post',
url: `${API_ENDPOINT}/api/setCue?Idx=${ID}&RDL=${props.val}`,
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-control-allow-origin': '*'
},
auth: {
username: 'admin',
password: 'password'
},
}).then(response => {
console.log("Delete Inside Axios");
}).catch(error => {
console.log("Error In Post Data", error);
});
console.log("Delete Key Press", ID, props.val);
}
}
<tbody>
{
PlaylistData && PlaylistData.map((playdata) => {
return (
<tr key={playdata.idx} tabIndex={playdata.idx} className="border_bottom"
KeyDown={(e) => handleKeyDown(e, playdata.idx)} onLoad={() => active(playdata.idx)}
>
<td style={{ color: "white", width: "200px" }}>
<img src={`data:image/jpeg;base64,${base64}`} alt="Clip Thumbnail" width="50%" />
</td>
when I click the delete button it does not send the table index but when I remove the window.addEventListener("keydown", handleKeyDown); its sending the id number but not the props values
I want both id and props values to print in the console.
How can I fix that?
please help.

You can get the value of target using event.code == "Delete". So replace event.key by event.code
You can see the example below to see how it works i.e. go to input and then press any key to see the key entered.
const input = document.querySelector('input');
const log = document.getElementById('log');
input.onkeydown = logKey;
function logKey(e) {
log.textContent += ` ${e.code}, `;
}
<input>
<h3 id="log"></h3>

Related

How to pass props to radio buttons in React.js

In React.js,
The name of the room assigned to each home appliance
is got from the backend and displayed
I am trying to check the room to which the home appliance belongs with a radio button.
What I want to achieve is
I want to check (reflect on) the radio button that matches the room name assigned to each home appliance.
Issue/error message
Nowhere is checked like a photograph below.
in DropDownForRoomChangeButton.js
Since I can confirm that the contents are properly contained with console.log(item.item.room_name)
I wonder why it wasn't checked.
DiscoverCondoRoom.js
const DiscoverCondoRoom = () => {
const [devices, setDevices] = useState([]);
const getDevices = async(data) => {
await axios.get('xxx.com',
{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${cookies.get('accesstoken')}`
},
})
.then(result => {
console.log(result.data)
setDevices(result.data.attributes);
})
.catch(err => {
console.log(err);
});
}
useEffect(() => {
getDevices();
},[]);
const keys = [
"camera",
"climate",
"cover",
"light",
"lock",
"sensor",
"switch",
];
const entities = keys
.map((key) => (devices[key] || []).map((e) => ({ ...e, key })))
.flat();
return (
<>
<div className="row mx-auto text-center">
{entities.map((entity, i) => (
<div className="">
<DropDownForRoomChangeBotton item={entity} />
</div>
</div>
}
</>
);
}
export default DiscoverCondoRoom;
DropDownForRoomChangeButton.js
import Dropdown from 'react-bootstrap/Dropdown';
const cookies = new Cookies();
const DropDownForRoomChangeButton = (item) => {
const [devices, setDevices] = useState([]);
const getDevices = async(data) => {
await axios.get('xxx.com',
{
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${cookies.get('accesstoken')}`
},
})
.then(result => {
console.log(result.data)
setDevices(result.data.attributes);
})
.catch(err => {
console.log(err);
});
}
const keys = [
"camera",
"climate",
"cover",
"light",
"lock",
"sensor",
"switch",
];
const entities = keys
.map((key) => (devices[key] || []).map((e) => ({ ...e, key })))
.flat();
const roomNames = [...new Set(entities.map((entity) => entity.room_name))];
const [val, setVal] = useState();
console.log(val)
const HomeHandleChange = e => setVal(e.target.value);
const CustomToggle = React.forwardRef(({ children, onClick }, ref) => (
<a
href=""
ref={ref}
onClick={(e) => {
e.preventDefault();
onClick(e);
}}
>
{children}
<button className="btn btn-primary button_table_rightside">Unassigned</button>
</a>
));
useEffect(() => {
getDevices();
setVal(item.item.room_nam)
},[]);
console.log(roomNames)
console.log(item)
console.log(item.item.room_name)
return (
<>
<Dropdown className="room_change_dropdown_top">
<Dropdown.Toggle as={CustomToggle} id="dropdown-custom-components" />
<Dropdown.Menu className="room_change_dropdown">
<Dropdown.Item className="room_change_dropdown_item">
{roomNames.map((room_names, i) => (
<div className="flex_radio">
<input
className="room_change_radio"
type="radio"
value={room_names}
onChange={HomeHandleChange}
checked={val === item.item.room_name}
/>
<p className="drop_down_p">{room_names}</p>
</div>
))}
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
</>
);
}
export default DropDownForRoomChangeButton;
HTML code
Based on your comment, I think you were going for something like this:
const homeHandleChange = e => setVal(e.target.name);
<input
...
name={item.item.room_name}
onChange={homeHandleChange}
checked={val === item.item.room_name}
/>
This way you set the state with the actual name of the room, not value, which in this case is meaningless.
Also, you don't need the useEffect for setting the initial state.
useState accepts a parameter for a default value.
So you can simply do:
const [val, setVal] = useState(item.item.room_name);
And then you can remove that line from the useEffect.
Note: Regular function, (unlike components / etc..), should be named in camel-case, not Pascal-case.
So HomeHandleChange, should actually be homeHandleChange like in the example above.
Obviously you can do whatever you choose but it's a matter of basic convention that's worth following IMO.

How to delete user by ID in react using react-confirm-alert

I'm trying to delete a user dependents by dependents id using react-confirm-alert dialog but the list refreshes, how do I stop this from happening?
import { confirmAlert } from 'react-confirm-alert';
import 'react-confirm-alert/src/react-confirm-alert.css';
//Api data sample
"Details": [
{
"name": "test test",
"gender" "M"
"dependents": [
{
"blood_group": "A+",
"date_of_birth": "1990-08-10",
"gender": "Female",
"genotype": "AS",
"id": "621f191dcd7fe69a6a3b7",
}
],
},
]
function App() {
const [formalDetails, setFormalDetails] = useState([]);
//get formal details API call
const handleDelete = (detail) => {
const params = JSON.stringify({
"principal enrid": detail.principals_enrid,
"dependent id": detail.id,
mine: true,
});
Axios({
method: "POST",
url: "api",
headers: {
"Content-Type": "application/json",
},
data: params,
})
.then((response) => {
console.log(response.status);
//below is where my proble lies
setFormalDetails((current) =>
current.filter((dep) => {
return dep?.dependents?.id !== detail?.dependents?.id;
})
);
})
.catch(function (error) {
console.log(error);
});
};
const submit = (user) => {
confirmAlert({
title: 'Confirm to delete Dependent',
message: `Are you sure you want to delete ${user?.name}?`,
buttons: [
{
label: 'Yes',
onClick: () => handleRemove(user)
},
{
label: 'No',
onClick: () => null
}
]
});
}
return (
<div className="app">
{formalDetails.length === 0 ? (<p>No Data</p>) : (
formalDetails?.map((record, idx) => {
return (
<div key={idx}>
<p >{record.name}</p>
<p >{record.gender}</p>
{
record?.dependents?.map((user, indx) => {
return (
<div key={indx}>
<p >{user.name}</P>
<button
onClick={() => submit(user)}
type="button">
Delete
</button
</div
)
}}
</div>
)
)}
</div>
);
}
export default App;
Please how do can I delete a dependent by ID without refreshing the list/page/window to keep the user scrolling down to take more action(s) even after performing a delete action.

how to send the url parameter query in react?

code:-
<div>
{ChannelName.map((val, index) => {
return (
<div className="TextLink" key={index}>
<NavLink to={`/`}
onClick={(e) => myClick(val, index)} >
<button className='notActive buttonLeft'
onClick={() => { handleOnClick(index); handleClick(val, index); setPage("Table") }} // pass the index
className={activeIndex === index ? "active" : "notActive"}>
{val}
</button>
</NavLink>
</div>
)
})
}
</div>
{page === "Table" ? <Table val={getname}/> : null}
2 component table url:-
const userId = props.val;
useEffect(() => {
setInterval(() => {
getData();
}, 300);
}, [userId]);
const getData = () => {
console.log(`inside${userId}`);
axios.get(`${API_ENDPOINT}/api/getPlaylist?RDL=${menuId}`, {
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Access-control-allow-origin': '*'
},
auth: {
username: 'admin',
password: 'password'
}
}).then(response => {
setIsLoading(true);
setPlaylistData(response.data.Clips);
setChannel([(response.data.Players)]);
// console.log("table", response.data.Clips);
//console.log([...Object.values(response.data.Players).flat()]);
}).catch(error => {
console.log("Error In GET Data", error);
});
I want when I click the menu then menu URL parameters goes to the menuId and then the api show according then
Right now i am props the the onclick name and when i click on the second button its show me new api and 1 menu api
how can i fix that?

I get an error when using reactjs useState

I am using reactjs. I am using the material-table to get the data with the editable table.
But I get an error like the picture, how can I fix this error?
I use useState for the edit settings of the table.
Please can you help with the error?
I do not receive any errors while receiving data. I just use editing on the table as active / inactive.
But
     const [, forceUpdate] = useState (false);
     const [data, setData] = useState (drBounty);
gives error for lines.
screenshot of the error and my source code below
import React, { Component, useState } from "react";
import withAuth from "../../components/helpers/withAuth";
import AlertMessageBox from "../../components/helpers/AlertMessageBox";
import { connect } from "react-redux";
import { Button, Col, Row, Table, Input } from "reactstrap";
import MaterialTable, { MTableEditRow } from "material-table";
import icons from '#material-ui/core/Icon';
import DeleteOutline from '#material-ui/icons/DeleteOutline';
import Edit from '#material-ui/icons/Edit';
class Bounty extends Component {
constructor(props) {
super(props);
this.state = {
isLoaded: true,
drBounty: [],
drList: [],
columns: [
{ title: 'Name', field: 'doctorName',
cellStyle:{padding: "1px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "1px"},
editComponent: (props) => (
<Input
type="text"
placeholder={props.columnDef.title}
defaultValue={props.value}
onChange={(e) => props.onChange(
this.setState({
doctorName: e.target.value
})
)}
/>
)
},
{ title: 'LastName', field: 'doctorLastName',
cellStyle:{padding: "1px", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis", maxWidth: "5px"},
editComponent: (props) => (
<Input
type={"text"}
placeholder={"Doktor soyadı"}
defaultValue={props.value}
onChange={(e) => props.onChange(
this.setState({
doctorLastName: e.target.value
})
)}
/>
)
}
]
};
this.getBountyList = this.getBountyList.bind(this);
}
async componentDidMount() {
await fetch(
`${this.domain}/api/user/groupusers?groupCode=`+
this.props.account_profile.profile.profile.groupCode,
{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
}
)
.then(res => {
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
console.log(json)
})
.catch(error => {
console.log(error)
return error;
});
}
async getBountyList(id) {
await fetch(`${this.domain}/api/bounty/list?groupCode=${this.props.account_profile.profile.profile.groupCode}&doctor=${id}`,{
headers: {
Authorization: `Bearer ${localStorage.getItem("id_token")}`,
"Content-Type": "application/json"
}
})
.then(res => {
console.log(res);
if (res.ok) {
return res.json();
} else {
return res.json().then(err => Promise.reject(err));
}
})
.then(json => {
console.log(json)
})
.catch(error => {
console.log(error);
return error;
});
}
render() {
const {isLoaded, drList, drBounty} = this.state;
const [, forceUpdate] = useState(false);
const [data, setData] = useState(drBounty);
const isRowUpdating = (rowData, status) => {
rowData.tableData.editing = status ? "update" : undefined;
forceUpdate(status);
};
if (!isLoaded) {
return <div>Loading...</div>;
} else {
return (
<div className={"animated fadeIn "}>
<Row>
<div> </div>
<Col sm={{span:1, offset:0.9}}>
<Table>
<thead>
<tr>
<th width={"20"} />
<th width={"50"}>Adı</th>
<th width={"70"}>Soyadı</th>
</tr>
</thead>
<tbody>
{
drList
.map(item => (
<tr key={item.id}>
<td>
<Button
block
outline
color="info"
onClick={() => this.getBountyList(item.id)}
>
Aç
</Button>
</td>
<td>{item.first_name} </td>
<td>{item.last_name}</td>
</tr>
))}
</tbody>
</Table>
</Col>
<MaterialTable
Icons={icons}
style={{height: "50", width: "50"}}
columns={ this.state.columns }
data={ this.state.drBounty }
actions={[
rowData => ({
icon: Edit,
tooltip: "Edit row",
onClick: (event, rowData) => {
isRowUpdating(rowData, true);
this.setState({
id: rowData.id,
user: rowData.user,
doctor: rowData.doctor,
doctorName: rowData.doctorName,
doctorLastName: rowData.doctorLastName,
totalBounty: rowData.totalBounty,
description: rowData.description,
customerName: rowData.customerName,
bountyDate: rowData.bountyDate,
createdDate: rowData.createdDate,
groupCode: rowData.groupCode
});
}
})
]}
components={{
EditRow: props => {
const newRowData = {
...drBounty, // *MUST INCLUDE tableData FROM ORIGINAL props.data!!*
id: "DEFAULT VALUES", // <-- // Set whatever default data you want here
doctorName: "ON EDIT" // <-- // (or pull from state, etc.. whatever you want)
};
return (
<MTableEditRow
{...props}
data={newRowData}
onEditingCanceled={(mode, rowData) => {
isRowUpdating(rowData, false);
}}
onEditingApproved={(mode, newData, oldRowData) => {
const dataCopy = [...drBounty];
const index = drBounty.indexOf(props.data);
dataCopy[index] = newData;
setData(dataCopy);
isRowUpdating(props.data, false);
}}
/>
);
}
}}
/>
</Row>
</div>
);
}
}
}
export default connect(withAuth( Bounty ));
You are trying to use the Hook (useState()) inside the render() method. Hooks can only be used inside of function components. However, you are using a class component so you have no need of this Hook.
Suggested Reading: https://reactjs.org/docs/hooks-state.html
Instead of using a Hook, you can use the following in your class component to accomplish the same results. Let's have a look :)
Initialize State in Constructor
this.state = { foo: bar };
You have already done this!
Update State with this.setState()
const [data, setData] = useState(drBounty);
Becomes ..
this.setState({data:drBounty});
However, you want to update the drBounty prop that you set up in the constructor, so you will want something more like this ..
this.setState({drBounty:someData})
Since that prop is an array, you will most likely want to spread (...) that data using the current array.
Re-Render without Updating State
As for your other implementation of useState() it appears you want to re-render without making any updates to state.
const [, forceUpdate] = useState(false);
However, instead you will want to simply use ...
this.render()

React runs function repeatedly, but I have not called it

I'm using react table (https://github.com/react-tools/react-table) to render a table of expenses. In one column, there should be a button to 'approve' the expense. This is handled like so:
const columns = [
{
Header: "Description",
accessor: "description"
},
{
Header: "Approve",
accessor: d => {
return <button onClick={this.approveExpense(d.id)}>Approve</button>;
},
id: "approved"
}
];
Where the approveExpense function is defined as:
approveExpense = id => {
fetch(`${apiRoot}expenses_pending/`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Token ${this.props.auth.token}`
},
body: JSON.stringify({
id: id
})
}).then(res => {
if (res.status === 200) {
this.setState({
issues: this.state.expenses.filter(expense => expense.id != id)
});
} else {
console.log("Error");
}
});
};
Strangely, however, when the page loads, it behaves as if all of these buttons are being repeatedly pressed, many times per second (until the fans start going crazy and I stop the react server).
Am I doing something stupid?
Full class:
class ExpensePendingAdmin extends Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
fetch(`${apiRoot}expenses_pending`, {
method: "GET",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Token ${this.props.auth.token}`
}
})
.then(response => response.json())
.then(data => {
console.log(data);
this.setState({
expenses: data
});
});
}
approveExpense = id => {
fetch(`${apiRoot}expenses_pending/`, {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json",
Authorization: `Token ${this.props.auth.token}`
},
body: JSON.stringify({
id: id
})
}).then(res => {
if (res.status === 200) {
this.setState({
issues: this.state.expenses.filter(expense => expense.id != id)
});
} else {
console.log("Error");
}
});
};
render() {
const columns = [
{
Header: "Description",
accessor: "description"
},
{
Header: "Logged At",
id: "loggedAt",
accessor: d =>
moment(d.expense_incur_datetime).format("HH:mm - ddd d/M/YYYY")
},
{
Header: "Amount",
accessor: d => `£${d.amount}`,
id: "amount"
},
{
Header: "Approve",
accessor: d => {
return <button onClick={this.approveExpense(d.id)}>Approve</button>;
},
id: "approved"
},
{
Header: "Paid",
accessor: d => {
console.log(d);
return d.is_unpaid ? "No" : "Yes";
},
id: "paid"
}
];
return (
<div className="container-fluid">
{this.state.expenses ? (
<>
<div className="row">
<div className="col text-center">
<h2>Pending Expenses</h2>
</div>
</div>
<div className="row">
<div className="col">
<ReactTable
data={this.state.expenses}
columns={columns}
minRows="0"
minWidth="50"
showPagination={false}
/>
</div>
</div>
</>
) : (
"LOADING"
)}
</div>
);
}
}
Methods in event handlers in JSX do not require parentheses, if you want to pass down a parameter simply wrap it in a function:
onClick={() => this.approveExpense(d.id)}
All other answers are right, however you could also improve the syntax of your function calling by making your function will multiple parameter sets :
approveExpense = id => ev => {
And then setting your accessor rendering like this :
accessor: d => <button onClick={this.approveExpense(d.id)}>Approve</button>;
The function : this.approveExpense(d.id) will return another function capable of receiving another parameter (here, the click event names ev) and will work like a charm
You need to pass the approveExpense() function as a callback function like, so it will only trigger when you click.
<button onClick={(d) => this.approveExpense(d.id)}>Approve</button>
The problem with your code is that you are passing the event handler in the wrong way:
return <button onClick={this.approveExpense(d.id)}>Approve</button>;
by using directly this.approveExpense(d.id) inside your JSX code you are telling javascript to execute that function as soon as the interpreter reads it.
Instead you should proxy the function execution on the click, like this:
return <button onClick={(e) => {this.approveExpense(d.id)}}>Approve</button>;
For more in depth explanation on how to pass function to components in React you can check https://reactjs.org/docs/faq-functions.html

Resources