i am working on a project with a react.js FE, a Node/Express.js BE and a database. I am currently working on a function which trigger my delete Route in BE. But my function trigger with every load and onlick, but should only trigger onClick.
Here are code samples of my service and my FE component. I am new to react.js so help would be apprechiated.
hardwareService.js:
static deleteHardware(hardwareId) {
console.log(hardwareId);
return axios.delete(hostname + '/hardware/' + hardwareId)
.then(response => {
return response;
})
}
component:
deleteOnClick = (id) => {
console.log('handleDelete wird ausgeführt!' + id);
HardwareService.deleteHardware(id);
}
html:
<tbody>
{this.state.hardware.map(hardware => (
<tr key={hardware.id}>
<td>{hardware.id}</td>
<td>{hardware.producer}</td>
<td>{hardware.model}</td>
<td>{hardware.type}</td>
<td>{hardware.serial_number}</td>
<td>{hardware.price}</td>
<td>{<Button variant="primary">Bearbeiten</Button>}</td>
<td>{<Button variant="primary" onClick=
{this.deleteOnClick(hardware.id)}>Löschen</Button>}</td>
</tr>
))}
</tbody>
Replace this line:
onClick={this.deleteOnClick(hardware.id)}>Löschen</Button>}
With this:
onClick={() => this.deleteOnClick(hardware.id)}>Löschen</Button>}
Explanation: in your current code you are calling the function immediately (when rendering the component) then passing the result as an event handler which has no effect. So you need to encapsulate the function call in another function for future call (arrow functions are well suited for that).
The hardware.id parameter will be enclosed in that function thanks to the JavaScript closure mechanism.
Related
This is an example of something I'd like to understand better syntactically in JSX.
Problem:
This works:
<button
onClick={ !isRecording ? beginRecording : endRecording } >
</button>
and this works:
<button
onClick={ () => { modalPortal.current.open() } } >
</button>
<Modal ref={modalPortal}>
<h1>Congratulations!</h1>
<p>If this modal opened, you find javascript syntax seamless and intuitive</p>
</Modal>
Together, no bueno.
<button
onClick={!isRecording ? () => {modalPortal.current.open();beginRecording} : endRecording } >
</button>
Error:
react-expected-an-assignment-or-function-call-and-instead-saw-an-expression
Detail:
This is inside a function component. isRecording & endRecording etc are are states in an object within the scope of the function component which defines the page I'm on in the app, modalPortal is a reference:
export default function RecordPage()
{
let [audioURL, isRecording, beginRecording, endRecording, timer] = RecorderContext();
const modalPortal = useRef(null);
...
}
I've also tried various permutations of passing this out to a single function that does the conditional evaluation etc
onClick={ doManyThings() } >
With and without arrows, both kinds of brackets and passing in arguments and without, none of it seems to work. I'd love a clear answer from someone knowledgeable!
References to things I've tried that don't work:
Conditional onClick from ternary
Call multiple functions onClick ReactJS
Setting conditional onClick behaviour in React Component
React: Expected an assignment or function call and instead saw an expression
You can move the ternary/branching logic into a single callback function.
<button
onClick={() => {
if (!isRecording) {
modalPortal.current.open();
beginRecording();
} else {
endRecording();
}
}
>
...
</button>
If you want to continue using the ternary though you need to also invoke the beginRecording function. The idea is similar here, based on the condition, return an anonymous function that does a couple things, or return a function reference that does whatever it does.
<button
onClick={!isRecording
? () => {
modalPortal.current.open();
beginRecording(); // <-- also invoke
}
: endRecording
}
>
...
</button>
Try this:
const handleButtonClick = () => {
if (isRecording) {
endRecording()
return
}
modalPortal.current.open()
beginRecording()
}
<button onClick={handleButtonClick} />
I wanted to create a button that shows the pop up to show the user that the OTP code has sent to their mobile phone, and also be able to link it to another "Verify OTP Code" page to let the user type in the verification code that is sent to their mobile phone. How do I create a button that calls two functions when it is being clicked? I tried the code below and it is not working at all. Can someone provide me an answer on how to create a button that calls two actions when it is clicked?
This my button in the HTML code:
<div class="col-md-12">
<div class="form-group">
<input type="text" id="number" name="phone" class="form-control" placeholder="Phone Number" required>
<br>
<div id="recaptcha-container"></div>
<button id="verify"class="block"type="button" onclick="one(); phoneAuth();">
Send Verification Code
</button>
</div>
</div>
This is my JavaScript code:
window.onload = function () {
render();
};
function render() {
window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('recaptcha-container');
recaptchaVerifier.render();
}
function one() {
window.location.href = 'insert.php';
}
function phoneAuth() {
//get the number
var number=document.getElementById('number').value;
//phone number authentication function of firebase
//it takes two parameter first one is number,,,second one is recaptcha
firebase
.auth()
.signInWithPhoneNumber( number, window.recaptchaVerifier )
.then(
function ( confirmationResult ) {
//s is in lowercase
window.confirmationResult = confirmationResult;
coderesult = confirmationResult;
console.log(coderesult);
alert("Message sent");
}
)
.catch(
function (error) {
alert(error.message);
}
);
}
function codeverify() {
var code = document.getElementById('verificationCode').value;
coderesult
.confirm(code)
.then(
function ( result ) {
alert("Phone Number Verified");
var user=result.user;
console.log(user);
}
)
.catch(
function ( error ) {
alert(error.message);
}
);
}
Just make one function buttonClicked() and set it onClick of the button:
function buttonClicked()
{
phoneAuth();
codeverify();
}
When the button is clicked, this function will run and fire the two inner functions. Make sure, that you place it after the both definitions of phoneAuth() and codeverify().
you are already sent to insert.php before you can do the phoneAuth().
So I would suggest you use ajax for calling insert.php like this
function one(){
$.ajax({
url: insert.php,
method: 'YOUR_METHOD_POST_GET_OR_OTHER',
success: function(result){
//Do something with the response if you want
},
error: function(xhr, status, error){
//Show error or something here
}
});
}
There are many ways to achieve what you're after...but my preference is simply to write a "controller function" that executes as many subfunctions as you need:
function one() {
// does the first thing
}
function two() {
// does another thing
}
function controller() {
one();
two();
}
<button id="verify" class="block" type="button" onclick="controller();">
That all being said, you CAN call multiple functions with your onclick. But I think the problem you're facing is that the first function you call (one()) is requesting another page (window.location.href). When your function executes, you're effectively leaving the page and unloading the javascript from memory. In other words, you may be aborting the the page/script before the second function has a chance to execute. You need to change the order of your functions, use a controller function and execute your functions within the controller in the appropriate order...or use ajax/async methods in your functions. Also...make sure you have spaces between all your html attributes in your button tag. You didn't have spaces between id, class, and type...and that might be causing the failure as well.
Additionally, this question has been answered before...
How do I create a button that calls two functions when it is being
clicked?
To add one or multiple event listeners to a DOM element, use addEventListener
See: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
To remove one or multiple event listeners from a DOM element, use removeEventListener
See: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/removeEventListener
With the above in mind, a clean, unobtrusive replacement for the inline attribute:
onclick="one(); phoneAuth();"
would be:
const verifyButton = document.getElementById('verify');
verifyButton.addEventListener('click', one, false);
verifyButton.addEventListener('click', phoneAuth, false);
I have this piece of code.
Where the problem I am facing is that is missing a prop which I want to be an id, obtained inside the map function.
Since I am unable to find a way to send the id to the component outside map, I figured I would do this:
This is my render function
render() {
var users = this.state.userList;
const Table = Reactable.Table,
Td = Reactable.Td,
Tr = Reactable.Tr;
if (users.length === 0) {
return <p>loading</p>
}
return (
<div class="maincontainer">
<div className="content-landing">
<Table
className="table"
filterable={['Email']}
itemsPerPage={8}
currentPage={0}
sortable={true}
>
{users.map((row) => {
return (
<Tr className={row.className}>
<Td column="Email">{row.email}</Td>
<Td column="Edit" ><FontAwesomeIcon className="editIcon" onClick={this.showModal(row.id)} icon={faEdit} /></Td> //----THIS.SHOWMODAL IS BEING AUTOEXECUTED WITHOUT ACCOUNTING FOR THE CLICKING
</Tr>
)
})}
</Table>
<EditUserModal show={this.state.showModal} close={this.closeModal} row={this.state.rowId}/> //---I WANT THIS TO RECEIVE A row.id FROM THE ABOVE MAP
</div>
</div>
)
}
I have written a couple comments in the parts where I want to make the changes.
I also thought about putting <EditUserModal> , inside the <Td> , but since its an external npm module it crashes, it only admits text.
So my solution was, to pass the row.id to the showModal function, and try to set is a state from there.
showModal(rowId) {
// console.log("showmodal state before any click")
// console.log(this.state.showModal)
console.log("triggered show modal")
console.log(rowId)
this.setState({
showModal: true,
rowId: rowId
}, () => {
// console.log("clicked show modal")
// console.log(this.state.showModal)
});
}
I think it should work, but since the function has a () , it auto executes without waiting for any click, making my app to crash.
In your code you are executing the function directly: this.showModal(row.id).
You have to use a callBack function to pass row.id something like:
onClick={()=> this.showModal(row.id)}
This should solve your problem.
You can use a callBack function in the onClick like this:
onClick={()=> this.showModal(row.id)}
Or you can define the showModal function like this:
showModal = (rowId) => () => {
...
}
and onClick={this.showModal(row.id)}
For people who does not understand arrow functions, the above solution is similar to this:
function showModal(rowId) {
return function () {
...
}
}
The showModal function returns another function that will be triggered in the onClick event.
I have an svg button that contains children elements(polygons). The handleMouseLeave function is used to set the state and then utilize its callback to update the children immediatley after. Even though the 'mouseleave' and 'callback' logs both fire in order, the rest of the code inside the callback area does not always fire.
Is there a better or correct way to handle the callback?
handleMouseLeave = (e) => {
console.log('mouseleave')
const polygons = [...e.target.children];
this.setState({
translate: "translateX(-100%)",
opacity: 0
}, () => {
console.log('callback')
polygons.forEach(child => {
child.style.transform = this.state.translate;
child.style.opacity = this.state.opacity;
});
});
};
--
render() {
return(
<button>
<HeroButtonSVG
id="HeroButton"
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
/>
<span>Check out my work<i className="fas fa-chevron-right"></i></span>
</button>
);
};
This seems to be an event binding issue, as class methods are not bound by default.
To solve this, you can add the following to the render function, which will bind the event, through using arrow functions to automatically bind:
<HeroButtonSVG
id="HeroButton"
onMouseEnter={e => this.handleMouseEnter(e)}
onMouseLeave={e => this.handleMouseLeave(e)}
/>
It turns out that the actual issue was derived from the pointer-events on the child SVG's. The issue was not related to React's setState callback function.
I tracked the issue here: https://github.com/facebook/react/issues/4492
I am in an event function and I would like to create a new alert popup (I am using the react-portal library):
onNewAlert: function(username) {
var divModal = (
<Portal ref={'Portal'+username}>
<div id={'div'+username}>
<br /><br/ >Alert for {username}
</div>
</Portal>);
...
}
But then I would have to call a function that is inside a Portal. I could normally do this with references if I was in the render() function, but I am in an event.
this.refs['Portal'+username].openPortal(); // openPortal is a function of the Portal component
Is there a way to call a component function for a component created on the fly in a javascript function?
Even if you could call portal.openPortal() it wouldn't do anything since the component created in the event handler wouldn't be attached to the DOM.
Instead of trying to render the Portal in the event handler function, the event handler should change the component state which will trigger render().
onNewAlert: function(username) {
this.setState({ showAlert: true });
}
The render() function would then use the state variable for the Portal component's isOpened property:
render: function () {
return (
<div>
...
<Portal isOpened={this.state.showAlert}>
...
</Portal>
</div>
);
}