Why triggered method? - javascript

I create REACT component and passes the method to call by pressing the button, using the Redux connect. There is a code:
const PageClientOne = ({onSubmit, onDelete, client}) => {
return(
<form style={styles.enter} onSubmit={_handleSubmit(client,onSubmit)}>
// ... something code
<Button type="submit" theme="success">Save</Button>
<Button type="button"
theme="error" onClick={onDelete(client._id)}>Delete</Button>
</form>
)
}
const _handleSubmit = (client, onSubmit) => {
return event => {
event.preventDefault()
onSubmit(client)
}
}
const mapStateToProps = (state, ownProps) => {
return {
client: state.reducers.clientsState.client
}
}
const mapDispatchToProps = (dispatch) => ({
onSubmit: (client) => {
dispatch(saveClient(client))
},
onDelete: (id) => {
console.log("DELETE")
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(PageClientOne)
The problem is that onDelete triggered when the page loads, and not only when clicked on the button. What am I doing wrong?

Its slightly different in React.
Change this,
<Button type="button" theme="error" onClick={onDelete(client._id)}>Delete</Button>
to,
<Button type="button" theme="error" onClick={()=>onDelete(client._id)}>Delete</Button>
Read here for more info,
https://facebook.github.io/react/docs/handling-events.html

(I'm not very familiar with React, so this could be wrong...)
When you create your <form> element, you define the button like this:
<Button type="button" theme="error" onClick={onDelete(client._id)}>Delete</Button>
Code in brackets – {onDelete(client._id)} – gets executed when the element is created (at page load), and the result it evaluates to is inserted into the element, not the code itself. You meant to have a normal onclick attribute; so put the code in quotes "" as in usual HTML:
onclick="onDelete(client._id)"

The issue is in onClick
<Button type="button" theme="error" onClick={onDelete(client._id)}>Delete</Button>
Instead of passing the callback function you are actually calling onDelete at the time of element creation.
Try
<Button type="button" theme="error" onClick={onDelete.bind(this, client._id)}>Delete</Button>
Hope it helps.

I hope my answer is corresponding to your question.
Looks like your delete button was submitting the form as you get the page refreshed.
So, you need to prevent the submit.
const mapDispatchToProps = (dispatch) => ({
onSubmit: (client) => {
dispatch(saveClient(client))
},
onDelete: (evt, id) => {
evt.preventDefault()
console.log("DELETE")
}
}
And on your delete button
<Button type="button" theme="error" onClick={(evt) => onDelete(evt, client._id)}>Delete</Button>

Related

How to insert 2 functions into onClick event ReactJS?

<Button onClick={submitHandler}>
I have this button which already has an assigned function to its onClick event. I also want to add <Button onClick={() => Toggle()}> this Toggle function into same button. How can I do it?
Simply create a function which calls both of the functions. Assuming submitHandler needs the event object, that will look like:
<Button onClick={(event) => {
submitHandler(event);
Toggle();
})}>
if you want to handle event you need to do onClick={(e) => { submitHandler(e); Toggle(); }.
if you don't want to handle event just do onClick={() => { submitHandler(); Toggle(); }.
First, think of separating your functions you can do something like :
<Button onClick={(e) => handleClick}>
And then create your functions which gonna look like:
const handleClick = (e) => { handleSubmit(e); handleToggle();}
You can later work on each function apart:
const handleSubmit() => { // your code }
const handleToggle() => { // your code }

React onClick function doesn't fire

I built this toy problem to replicate an issue I am facing in a larger app. Why does handleClick not fire when the button is clicked?
const Button = () => <button type="button">Click me</button>;
export const App = () => {
const handleClick = () => {
console.log("clicked");
};
return <Button onClick={handleClick} />;
};
You pass onClick={handleClick} as a property to Button but the Button component does not use the property.
const Button = () ... // ⚠️ no onClick property used
You can fix this by responding to the onClick property -
const Button = ({ onClick }) => // ✅
<button type="button" onClick={onClick}> // ✅
Click me
</button>
An obvious improvement would be to respond to the children property as well. This allows the caller of Button to write anything in place of the static Click me -
const Button = ({ onClick, children }) =>
<button type="button" onClick={onClick}>{children}</button>
<Button onClick={handleRegister}>Register</Button>
<Button onClick={handleLogin}>Login</Button>
<Button onClick={handleSave}>Save</Button>
Note children can be passed as a property. Sometimes you will see components use children in this way. Both examples function identically -
const Button = ({ onClick, children }) =>
<button
type="button"
onClick={onClick}
children={children}
/>
Another common thing for Button components like this is to automatically prevent the default event for the onClick handler. We can also accept a type property and set the default to "button" if the caller does not otherwise specify -
const Button = ({ type = "button", onClick, children, preventDefault = true }) =>
<button
type={type}
onClick={e => {
if (preventDefault) e.preventDefault()
onClick(e)
}}
children={children}
/>
<Button type="submit" onClick={handleRegister}>Register</Button>
<Button onClick={handleReset} preventDefault={false} children="Reset" />

How can I send the button ID from onClick to handleClick in Typescript

so here is what i'm trying to do. I have 3 buttons in material ui and I gave each one of them and id. I want to send the id through a onClick to a single handleclick function that then runs a switch case and determines which button pressed the id and then sets the state accordingly. This is because I want to have so when a button is clicked, it sets a key value that i specifiy depending on which one what clicked. Here is my code below
const [key, setKey] = useState("");
const handleClick = (e: MouseEvent<HTMLElement>) => {
const target = e.target as Element;
const id = target.id;
alert(id);
};
async function register(e: Event) {
e.preventDefault();
try {
const registerData = {
firstName,
lastName,
username,
password,
passwordVerify: passwordConfirm,
key: { key },
};
} catch (err) {
console.error(err);
}
}
<Button
id="btn1"
className={classes.buttonStyle}
onClick={handleClick}
>
Student
</Button>
<Button
id="btn2"
className={classes.buttonStyle}
onClick={handleClick}
>
{" "}
Ta{" "}
</Button>
<Button
id="btn3"
className={classes.buttonStyle}
onClick={handleClick}
>
{" "}
Admin{" "}
</Button>
My problem is that whenever I click the button on the react page, it shows an empty alert sometimes and other times it shows up with the button. Idk why that's the case. the alert is to test if i'm actually getting an id from the button press.
can someone tell me the types I need to be adding for this to work. Thanks
It should be as follows. The correct event triggered is a mouseEvent.
You can access Id with event.currentTarget instead of event.target
import { MouseEvent } from 'react';
...
const handleClick = (e: MouseEvent<HTMLElement>) => {
const id = e.currentTarget.id;
console.log(id);
}
...
<Button
...
onClick={handleClick}
/>
...
Change Event type to MouseEvent<HTMLButtonElement>
import { MouseEvent } from 'react'
// ... some code
const handleClick = (e: MouseEvent<HTMLButtonElement>) => {
const id = e.currentTarget.id;
console.log(id);
}
Further, for a small performance gain, it is better to declare handleClick using useCallback
import { useCallback, MouseEvent } from 'react'
// ... more code
const handleClick = useCallback((e: MouseEvent<HTMLButtonElement>) => {
const id = e.currentTarget.id;
console.log(id);
}, []);
Edit: modify answer after question edits.
so I was getting an empty alert because of the setKey line. Once I removed it, the alert showed the right key (along with changing target to currentTarget. Thanks everyone for the help

React Redux: Posting Records partly work with onclick function

I have the following code in React Redux. Everything works fine by posting records to server backend as per code below.
handlePostId(postid,post_content){
return (e) => this.props.dispatch(Actions.sendData(postid,post_content));
}
<input type="button" value="Post" onClick={ this.handlePostId(post1.id, 55)} />
Here is my issue.
If I change onclick function to code below
<input type="button" value="Post" onClick={() => this.handlePostId(post1.id, 55)} />
It will not post records to server backend. And no error is shown in the console is it because of this () =>. please how do I rectify this
Here is the entire code
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { Actions } from '../actions';
class App extends React.Component {
constructor(props) {
super(props);
this.state = {};
}
componentDidMount() {
this.props.dispatch(Actions.getRec());
}
handlePostId(postid,post_content){
return (e) => this.props.dispatch(Actions.SendData(postid,post_content));
}
render() {
const { post1, posts1} = this.props;
return (
<div>
{posts1.items1 &&
<ul>
{posts1.items1.map((post1, index1) =>
<li key={post1.id}>
{post1.content} ({post1.id})
<input type="button" value="Post working" onClick={ this.handlePostId(post1.id, 55)} />
<input type="button" value="Post Not Working" onClick={() => this.handlePostId(post1.id, 55)} />
</li>
)}
</ul>
}
</div>
);
}
}
function mapStateToProps(state) {
const { posts1, post1 } = state;
return {
post1,
posts1
};
}
const connectedApp = connect(mapStateToProps)(App );
export { connectedApp as App };
As the other people said, you're returning a function that returns a function that does something, instead of returning a function that does something. You should choose between:
handlePostId(postid, post_content) {
return (e) => this.props.dispatch(Actions.SendData(postid,post_content));
}
// ..
onClick={this.handlePostId(post1.id, 55)}
and
handlePostId(postid, post_content) {
return this.props.dispatch(Actions.SendData(postid,post_content));
}
// ..
onClick={() => this.handlePostId(post1.id, 55)}
Alternatively, you can add a mapDispatchToProps and declare it there, like
function mapDispatchToProps(dispatch) {
return {
handlePostId: (postid, post_content) => {
return dispatch(Actions.SendData(postid, post_content));
},
};
}
const connectedApp = connect(mapStateToProps, mapDispatchToProps)(App);
and in your render method you can do
// ...
const { post1, posts1, handlePostId } = this.props;
// ...
onClick={() => handlePostId(post1.id, 55)}
handlePostId(postid,post_content){
return (e) => this.props.dispatch(Actions.sendData(postid,post_content));
}
This returns a function which takes a parameter (presumably an event object):
<input type="button" value="Post" onClick={this.handlePostId(post1.id, 55)} />
In order to rewrite the <input/> tag as
<input type="button" value="Post" onClick={() => this.handlePostId(post1.id, 55)} />
you need to also modify handlePostId() to handle the event directly rather than returning a function:
handlePostId(postid,post_content){
return this.props.dispatch(Actions.sendData(postid,post_content));
}
You are using a curried function in your handlePostId method. This means you are returning another function from it. By doing that you can use event object without using an arrow function in your click handler. So this works:
onClick={this.handlePostId(post1.id, 55)}
But if you add an onclick handler again (arrow function) you should invoke it like that:
onClick={() => this.handlePostId(post1.id, 55)()}
Notice the extra () at the end of the function. But, you are not using event object in your handler method, hence you can simply remove the extra function and return your action dispatching like that:
handlePostId(postid,post_content) {
return this.props.dispatch(Actions.sendData(postid,post_content));
and use it like:
onClick={() => this.handlePostId(post1.id, 55)}
Also, if you want to use event object like that and prefer using a curried function then you shouldn't use arrow function in your onclick handler.
onClick={this.handlePostId(post1.id, 55)}
This is enough to use the event object and curried function's goodies. But since you are not using event object I'm not quite sure you wrote this curried function deliberately.

Setting/Clearing input in Redux/React

I would like to know how one can wire in a clear field via redux when using react.
For instance, I have a form with some sample code.
<Field component={datewidget} id ="date" name="date" type="date" label="date" />
<button type="button"onClick={() => {(clearMyInput());}}>
</button>
The function clearMyInput is dispatched such that:
const mapDispatchToProps = (dispatch) => {
return {
clearMyInput: () => {
return dispatch(clearDate(datedata,value));
}
}
}
My question how can one clear the input field by simply clicking on the button and setting the value of the input to none.
For example in jquery, i can write something like this:
$("#button").click(function () {
$("#date").val("");
});
I would like to know how one can do this using redux forms in react.
In your Field's component, pass attribute value from your store and attach event handler to dispatch change.
<Field
component={datewidget}
id="date"
name="date"
type="date"
label="date"
value={this.props.fieldValue}
onChange={this.props.changeFieldValue}
/>
Then with dispatching clearDate function, you just need to set all form's values to ''. I recommend to look into Redux Form which do this all without boilerplate.
I do want to add as a supplement to the existing answer that there is built-in functionality for clearing a form:
<button type="button" onClick={reset}>
Clear Values
</button>
Notice the {reset} onClick action handler here. This comes out of the box with Redux-Form
import { reset, destroy } from 'redux-form'
//
//..code Block
render() {
const { resetForm, destroyForm } = this.props
return <ComponentName {...{ resetForm, destroyForm }} {...this.props} />
}
}
// #formName: for global use(in case if you render more than one form from this container..)
const mapDispatchToProps = dispatch => ({
resetForm: formName => dispatch(reset(formName)),
destroyForm: formName => dispatch(reset(formName)),
})
and now you call it from the component
const ComponentName = ({ resetForm, destroyForm }, ...props) => {
//..code Block
<button type='submit' onClick={() => resetForm('formName') && destroyForm('formName')} > Clear </button>
}
HAPPY CODING..

Categories

Resources