I am using React and Redux. At some point, I have a Link, and I would like to add a delay to this Link before changing the route.
render(){
return(
<div>
<h3>New note for {this.props.match.params.user}</h3>
<input placeholder="Your note" onChange = {(e)=>this.handleChange(e)}/>
<Link to={`/board/${this.props.match.params.user}`} >
<br/>
<button onClick={(e) => {this.validateNote()}}>Add this now !</button>
</Link>
</div>
);
}
How can I do that ?
As #shubham-khatri wrote in the comments, I would definitely use a programmatic way to navigate instead of a Link component.
Have a look here.
To answer the specific problem, as you already have a button inside the link, i would use it's callback to change the routing.
<button onClick={(e) => {this.validateNote(); this.props.history.push(`/board/${this.props.match.params.user}`);}}>Add this now !</button>
If we're already talking, I wouldn't recommend you the use an anonymous function as a callback to the onClick because that way you create a new function each render.
Try to read about it here
Related
so i have a form component having button array,
though i used icons in it with value attribute. just like below.
<button value={'admin'} onClick={(e)=> handleClick(e.target.value)}>
<FaUserSecret classname="text-lg" />
</button>
in handleClick function e.target.value is returning icon instead of admin.
Thanks in advance 😄💗.
I tried to pass e as parametter and use its value in function but still same.
Can you please elaborate or share more code with us. Cause I tried your given code and it's working fine. I am getting 'admin' as the output.
<div className='App'>
<button value={'admin'} onClick={(e)=> console.log(e.target.value)}>
Click
</button>
</div>
Try this:
<button value={'admin'} onClick={e => handleClick(e.target.value)}>
<FaUserSecret classname="text-lg" />
</button>
You're not supposed to use parenthesis around "e".
You can use e.currentTarget.getAttribute("value") method to get the admin value assigned to the button.
CodeSandbox code reference
Difference b/w e.target and e.currentTarget - difference-between-e-target-and-e-currenttarget
I pass 2 values to a child component:
List of objects to display
delete function.
I use a .map() function to display my list of objects(like in the example given in react tutorial page), but the button in that component fires the onClick function, on render(it should not fire on render time). My code looks like this:
module.exports = React.createClass({
render: function(){
var taskNodes = this.props.todoTasks.map(function(todo){
return (
<div>
{todo.task}
<button type="submit" onClick={this.props.removeTaskFunction(todo)}>Submit</button>
</div>
);
}, this);
return (
<div className="todo-task-list">
{taskNodes}
</div>
);
}
});
My question is: why does onClick function fire on render and how to make it not to?
Because you are calling that function instead of passing the function to onClick, change that line to this:
<button type="submit" onClick={() => { this.props.removeTaskFunction(todo) }}>Submit</button>
=> called Arrow Function, which was introduced in ES6, and will be supported on React 0.13.3 or upper.
Instead of calling the function, bind the value to the function:
this.props.removeTaskFunction.bind(this, todo)
MDN ref: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
The Problem lies in how you pass your function
At the moment you are not passing the function but Calling it instead:
<Button onClick={yourFunction()} />
You can Fix this in two ways:
<Button onClick={() => yourFunction(params)} />
Or if you dont have any params:
<Button onClick={yourFunction} />
The value for your onClick attribute should be a function, not a function call.
<button type="submit" onClick={function(){removeTaskFunction(todo)}}>Submit</button>
you need to use an arrow function with onClick in order to prevent immediately invoke.
so if your button looks like this :
<button onClick={yourfunctionname()} />
it must be like this :
<button onClick={() => yourfunctionname(params)} />
JSX is used with ReactJS as it is very similar to HTML and it gives programmers feel of using HTML whereas it ultimately transpiles to a javascript file.
Writing a for-loop and specifying function as
{this.props.removeTaskFunction(todo)} will execute the functions
whenever the loop is triggered .
To stop this behaviour we need to return the function to onClick.
The fat arrow function has a hidden return statement along with the bind
property. Thus it returns the function to OnClick as Javascript can
return functions too !!!!!
Use -
onClick={() => { this.props.removeTaskFunction(todo) }}
which means-
var onClick = function() {
return this.props.removeTaskFunction(todo);
}.bind(this);
For those not using arrow functions but something simpler ... I encountered this when adding parentheses after my signOut function ...
replace this <a onClick={props.signOut()}>Log Out</a>
with this <a onClick={props.signOut}>Log Out</a> ... ! 😆
JSX will evaluate JavaScript expressions in curly braces
In this case, this.props.removeTaskFunction(todo) is invoked and the return value is assigned to onClick
What you have to provide for onClick is a function. To do this, you can wrap the value in an anonymous function.
export const samepleComponent = ({todoTasks, removeTaskFunction}) => {
const taskNodes = todoTasks.map(todo => (
<div>
{todo.task}
<button type="submit" onClick={() => removeTaskFunction(todo)}>Submit</button>
</div>
);
return (
<div className="todo-task-list">
{taskNodes}
</div>
);
}
});
I had similar issue, my code was:
function RadioInput(props) {
return (
<div className="form-check form-check-inline">
<input className="form-check-input" type="radio" name="inlineRadioOptions" id={props.id} onClick={props.onClick} value={props.label}></input>
<label className="form-check-label" htmlFor={props.id}>{props.label}</label>
</div>
);
}
class ScheduleType extends React.Component
{
renderRadioInput(id,label)
{
id = "inlineRadio"+id;
return(
<RadioInput
id = {id}
label = {label}
onClick = {this.props.onClick}
/>
);
}
Where it should be
onClick = {() => this.props.onClick()}
in RenderRadioInput
It fixed the issue for me.
It is possible to achieve this even in more readable way than:
<button onClick={() => somethingHere(param)}/>
const Comp = () => {
const [triggered, setTriggered] = useState(false);
const handleClick = (valueToSet) => () => {
setTriggered(valueToSet);
};
return (
<div>
<button onClick={handleClick(true)}>Trigger</button>
<div>{String(triggered)}</div>
</div>
);
};
That way it won't fire the state setter and won't cause too many re-renders compared to <button onClick={setTriggered(true)}/>
which is okay if you don't have any params to pass to the function.
That's because you are calling the function directly instead of passing the function to onClick
If you have passed down onClick={onClickHandler()} then, the function onClickHandler() will be executed during the time of rendering too, the () instructs to execute the function as soon as it is rendered , which is not desired here , instead we use onClick={onClickHandler} , this will execute the onClickHandler only when the specified event occurs. But if we want to pass down a argument along with the function then we can make use of ES6 arrow function.
For your Case :
<button type="submit" onClick={() => this.props.removeTaskFunction(todo)}>Submit</button>
Bit late here but here is the simple answer.
direct approach will trigger by itself due to JS DOM rendering
onClick={this.props.removeTaskFunction(todo)}
anonymous arrow function approach. it will trigger on click
onClick={()=>this.props.removeTaskFunction(todo)}
You are not passing the function as an argument you are calling it directly that why it launches on the render.
HOW TO FIX IT
there are two ways:
First
<Button onClick={() => {
this.props.removeTaskFunction(todo);
}
}>click</Button>
OR
Just bind it
this.props.removeTaskFunction.bind(this,todo);
How come the following React Button Emitter is not working? It should display the word Apple, with button click.
function App() {
return (
<div>
<button onClick={handleClick('apple')}>
Test Button
</button>
</div>
)
}
function handleClick(props) {
console.log(props)
}
In order for it to get called on click you need to pass a function. Right now your code is invoking the function:
function App() {
return (
<div>
{/* Creates an anonymous function that calls `handleClick` */}
<button onClick={() => { handleClick('apple'); }}>
Test Button
</button>
</div>
)
}
By doing onClick={handleClick('apple')} what you are doint is to put the result of handleClick('apple') at rendering time, not onClick time.
onClick={() => handleClick('apple')} will work because you are creating a function and assign it to onClick, without executing it yet.
This is how React works, because what you are writing is actually just javascript (not html, even if it looks like so).
Your way would instead be perfectly ok if you were using Vue, for example, because in that case you are working in an html template (unless you don't want to use jsx..)
I'm trying to access the img tag's src attribute. By using e.target, it gives me the entire tag set, but I thought I could access by doing e.target.img.src, but it didn't work. How can I do that?
handleClickOpen(e) {
console.log(e.target);
}
<Button onClick={this.handleClickOpen}>
<img src={image.image} alt="product" />
</Buttonz>
If you need the value of the src property AND the handler for the synthetic event, you can use a lambda function and pass it as a second parameter, like this:
handleClickOpen(event, imageSrc) {
console.log(imageSrc);
}
<Button onClick={ event => this.handleClickOpen(event, image.image) }>
<img src={image.image} alt="product" />
</Button>
Consider that this is just a fast solution, it isn't the very best practice, inline lambdas aren't properly adviced and everything.
You should be aveare of how event is working.
e.target is the deepest element user is clicking on. Consider example bellow.
<button onClick={(e) => {console.log(e.target)}} style={{padding: '20px',}}>
<img src={'someUrl'} alt="product" />
</button>
If user clicks directly on image e.target === <img src="someUrl" alt="product">. If user clicks on padding of the button e.target === <button style="padding: 20px;">
I would recommend to use react ref here. So you can save ref to your image and call it when you need.
I'm trying to set the inner HTML of an alert div, but receiving the error message : Can only set one of 'children' or props.dangerouslySetInnerHTML'.
Why does this happen ?
function alertContent(alert) { return {__html: alert.text} }
const Alerts = ({ alerts=[{level: 'warning', text:'<p>Warning message!</p>'}], onDismiss }) => (
<div className="alerts">
{alerts.map(alert =>
<Alert
bsStyle={alert.level}
key={alert.id}
onDismiss={onDismiss}
dangerouslySetInnerHTML={alertContent(alert)}
></Alert>
)}
</div>
)
I had this error message in a react application.
My issue was I had code as below
<p dangerouslySetInnerHTML={{ __html:stringContainingHtml}}> </p>
My issue was the space in the <p> </p> tags - since html gets injected inside these tags the space was causing an issue as it wasn't empty.
Hope this might help some people.
This happens because dangerouslySetInnerHTML can only be applied to one element. In your case, <Alert/> is a complex element made up of multiple children. That being said, the BS Alert component does accept HTML:
<Alert bsStyle="warning">
<strong>Holy guacamole!</strong> Best check yo self, you're not looking too good.
</Alert>
or
<Alert bsStyle="warning">
<span dangerouslySetInnerHTML={alertContent(alert)} />
</Alert>
Solution, You have to make a separate component to render element in which you are using dangerously set.....
For Example:
const RenderHTML = (props) => (<span dangerouslySetInnerHTML={{__html:props.HTML}}></span>)
YourData.map((d,i) => {
return <RenderHTML HTML={d.YOUR_HTML} />
})
you have to close the html tag short hand if there aren't inner HTML
<Alert dang...={} />
instead <Alert></Alert>
I have solved this issue myself.
When you are recursively rendering a component, you must separate out the part of the component where dangerouslySetInnerHTML is being used into another component and then use that component in the one you are recursively rendering.