How to pass parameters to a function when using React stateless components? - reactjs

I have a component like this (very simplified version)
const MyComponent = () => {
const handleClick = param => {
console.log(param);
}
return (
<Link to={'/'} onClick={handleClick} value={'a string'}>
);
}
How can I pass a parameter to the handleClick function?

you have to pass a function to onClick. onClick will always call your functions with an event parameter. So if you pass a function like this:
onClick={handleClick}
It will be called like this:
onClick={(event) => handleClick(event)}
So to pass parameters to a function you can do something like this instead:
onClick={() => handleClick(parameters)}

Related

TypeScript / React - Trying to Create My Own Button Issue - Function Signature Problem

I'm trying to create a simple button in React / TypeScript.
I'm not sure where I am getting the syntax for this incorrect.
Editors don't seem to like the ' => void ' part of my signature.
My goal is to be able to pass down a "clear state" type handler from any parent component.
import React from 'react';
import ClearIcon from '#material-ui/icons/Clear';
// problem is on this line
export function ClearButton(props: {onClick: (React.MouseEvent<HTMLElement>) => void}) {
return (<span
onClick={(e) => { props.onClick(e) }}>
<ClearIcon /></span>);
}
I believe you forgot the name of the function's parameter.
Example:
onClick: (e: React.MouseEvent<HTMLElement>) => void
Also, the actual onClick on the span should probably be assigned like so:
onClick={(e) => props.onClick(e)}>
Alternatively, you could use a shorter syntax in this case, if you prefer.
onClick={props.onClick}>
So your code becomes:
export function ClearButton(props: {onClick: (e: React.MouseEvent<HTMLElement>) => void}) {
return (
<span onClick={(e) => props.onClick(e)}>
<ClearIcon />
</span>
)
}

Initiate function/event from child to parent

In my parent component I have a function/event that looks like this:
const onClick = e => {
e.preventDefault();
POST('/api', { data: data }).then(
async (response) => {
const json = await response.json()
setData(json.data)
}
)
}
On the parent component, this is initiated by the following:
<button type="button" onClick={onClick}>Click me</button>
However, I also have a child component, where I would like a click event in that to also initiate this function/event and a . How is that done ?
I tried just doing something like:
<ChildComponent onclick={onClick} data={data} setData={setData} />
And then in the child component just doing something like:
<div onClick={() => {props.setData(i); props.onClick;}}>
But that doesn't seem to work.
So any hints to what I'm doing wrong here ?
I am not sure if this will fix your problem, but it seems you are using incorrectly the function prop.
Try this:
<div onClick={(e) => {props.setData(i); props.onClick(e);}}>
You can use functions in onClick in 2 ways:
1 - Assign the prop function itself to the onClick:
<div onClick={props.onClick}>
2 - Assign a callback to the onClick which calls the function with the event:
<div onClick={(e) => props.onClick(e)}>
To summarize: the onClick needs to receive a function, but your problem was you were assigning a callback (this is correct) which was not calling the props.onClick one
[you were doing props.onClick instead of props.onClick()]
You should update the state in the parent, not in the child. I am not sure why you are calling props.setData in the child when you can handle that in the parent onClick function.

How do i setState onClick

Hi so i got my react function with a state that i use to know which componont should be rendered at a given time; here is my main App Function (i only include the function not the rest of class since it is not relevent)
My app function
function App(){
const [menuState, setMenuState] = useState('journal');
return(
<>
<button onClick={setMenuState('journal')}>JOUNRAL</button>
<button onClick={setMenuState('stats')}>STATS</button>
<MenuHandler menu={menuState}/>
</>
);
}
My MenuHandler function
function MenuHandler(props) {
const menu = props.menu;
if(menu==="journal")
return (<Journal />);
if(menu==="stats")
return (<Stats />);
return (<Journal />);
}
When i do this i get an infinite loop and i can't figure out why.
The problem is that you are calling setMenuState on each render, therefore the infinite loop. You are not assigning it to the onClick handler, pass an arrow function like this to solve it:
<button onClick={() => setMenuState('journal')}>JOUNRAL</button>
<button onClick={() => setMenuState('stats')}>STATS</button>

Handle children.props

so, in ParentComponent I have
<Component dropDownContent={<DropDownContent content={array} onSelect={handleSelect} />} />
my DropDownContent looks something like this
return (<ul>
{content.map((item) =>
{ return <li><button onClick={()=> onSelect(array.id)}>{array.name}</button></li>}
)}
</ul>)
Can I some how do something with the onSelect inside Component even if I add DropDownContent as a prop to Component?
Thanks :)
What I understand from your question is that you want to pass a function from the parent component to the child component. And when a local function inside child component is clicked, you want to call that passed function. if yes, then this is your solution:
Note: I do not know exactly what code you wrote and what your component consists of. So I will give you the answer by giving a simple example to fully understand the solution.
In your parent component:
export const ParentComponent = props => {
const handleSelect = () => console.log(`do something here`);
return (
<Component
dropDownContent={
<DropDownContent
content={array}
onSelect={() => handleSelect()}
/>}
/>
)
}
And in your child component you need to receive the passed function like below:
export const ChildComponent = props => {
const handlePassedFunction = () => props.onSelect?.();
return (<ul>
{content.map((item) => {
return <li>
<button onClick={() => handlePassedFunction(array.id)}>{array.name}</button>
</li>
}
)}
</ul>)
}

How to get multiple refs to use the same handleClick function?

I have a few similar elements:
<div ref={this.ref1} onClick={this.handleClick} className="icon-wrapper"></div>
<div ref={this.ref2} onClick={this.handleClick} className="icon-wrapper"></div>
<div ref={this.ref3} onClick={this.handleClick} className="icon-wrapper"></div>
In my constructor, I declare these refs:
constructor(props) {
super(props);
this.ref1 = React.createRef();
this.ref2 = React.createRef();
this.ref3 = React.createRef();
}
I'm trying to pass these refs to their respective handleClick() functions. Something like:
<div ref={this.ref1} onClick={this.handleClick(ref1)} className="icon-wrapper"></div>
or
<div ref={this.ref1} onClick={this.handleClick(this.ref)} className="icon-wrapper"></div>
And I'm trying to handle the ref in the handleClick function like this:
handleClick = (ref) => {
console.log(ref);
}
And just as a ridiculously wild guess, I tried:
handleClick = () => {
console.log(this.ref.current);
}
That all seems dead wrong because onClick={this.handleClick(ref)} would invoke the function immediately, which is not what is wanted from a click function.
How do you pass different refs to the same function so that the function knows who called it?
The main issue here is you are invoking the function immediately. Thats what applying () does to the end of a function. Instead you need to pass a callback function that needs to be invoked by the event. This is done by passing the function reference.
You can use bind here if you need to pass a value. .bind will return a new function to be invoked. null as the first argument is for the this context, null wont change its context assuming its already been bound to your class. If you need to bind this method you can just pass this through instead of null.
I would recommend passing something to map though instead of the whole ref, like so
<div ref={this.ref1} onClick={this.handleClick.bind(null, 'ref1')} className="icon-wrapper"></div>
then you would access like so
handleClick = (ref, event) => {
if (!this[ref]) return
console.log(this[ref].current);
}
Most use cases for passing a parameter to your function would be because you need a specific key. In this case it looks like you just want to access the element itself. You can get that from the event itself.
<div onClick={this.handleClick} className="icon-wrapper"></div>
handleClick = (event) => {
console.log(event.target);
}
The answer to your question is to use a lambda method,
<div ref={this.ref1} onClick={() => this.handleClick(this.ref1)} className="icon-wrapper"></div>
<div ref={this.ref2} onClick={() => this.handleClick(this.ref2)} className="icon-wrapper"></div>
<div ref={this.ref3} onClick={() => this.handleClick(this.ref3)} className="icon-wrapper"></div>
But if what you want to do is to access the target that fired the event, you can use
handleClick = (event) => {
console.log(event.target);
}
<div onClick={this.handleClick} className="icon-wrapper"></div>
Edit: Here are some alternatives with better (marginal) performance.
handleClick1 = () => this.handleClick(this.ref1)
handleClick1 = this.handleClick.bind(this, this.ref1)
render() {
return (<div ref={this.ref1} onClick={this.handleClick1} className="icon-wrapper"></div>)
}

Resources