Set the on click method conditionaly in a component - reactjs

I have a component with an onClick method, where I would like to set the method conditionaly based on the property I get in the component. This is how to code looks like:
<Image
className={styles.editIcon}
src={openForm ? editPeriodDisabled : editPeriod}
onClick={() => toggleFormCallback(id)}
alt="Rediger periode"
/>
I have a boolean property openForm, by which I would like to set the method in the onClick property of the Image component. So, something like this for example:
openForm ? null : toggleFormCallback(id)
But, not sure how to do that with an arrow function?

You can use bind():
onClick={openForm : null ? toggleFormCallback.bind(this, id)}
bind() returns a new function which is the same as the original but bound to the given context. You can also bind some or all of the parameters.

The easiest solution.
<Image
className={styles.editIcon}
src={openForm ? editPeriodDisabled : editPeriod}
onClick={() => { if (openForm) { toggleFormCallback(id) } }}
alt="Rediger periode"
/>

Related

How to get value of data custom-attribute in JSX / React

Let's say I create a data-custom attribute in JSX element to save some meta-data about that element.
Like:
return (
<button data-customData="red" onClick={(ev) => { console.log(ev.target.customData)}}>Teste</button>
)
If I try to acess the data-custom attribute like you see in the code I will get undefined.
But If I try something like ev.target.style or ev.target.id I will not get undefined.
What is the difference and how can we acess this value ?
you're not calling the right value, you are calling a property called customData but the attribute name is data-customData, and in order to get the value you need to change how you call the attribute using the getAttribute function that the element (ev.target) provides
return (
<button
data-customData="red"
onClick={(ev) => {
const element = ev.target;
console.log(element.getAttribute("data-customData"));
}}
>
Click Me
</button>
)
The thing you're trying to is not a very common pattern and if you want to get a value from the user you should use the right control (input, radio, select) instead of using a data attribute.

React onClick target.value undefined

I'm using Antd to generate Tags and I want to modify state using onClick event.
My parent Component (Where I generate a List of Items)
onRiskClick(e) {
e.preventDefault();
console.log(e.target);
console.log(e.target.value);
}
[...]
render() {
return (
[...]
<div className="square risk_orange">
<RenderingRiskMatrix
risks={this.state.risks}
impact="2"
likelihood="5"
color="red"
onRiskClick={this.onRiskClick} <-- passing onRiskClick function as props
></RenderingRiskMatrix>
</div>
My Child Function RenderingRiskMatrix
<Tooltip key={risk.id} title={risk.name}>
<Tag
key={risk.id}
color={props.color}
onClick={(event) => props.onRiskClick(event)}
>
{risk.id}
</Tag>
</Tooltip>
What I got in console :
<span class="ant-tag ant-tag-red" ant-click-animating-without-extra-node="false">R028</span>
undefined
which means e.target exists and not e.target.value which should be R028 no ?
Thanks,
I think there is a simpler way to accomplish your goal. The value you want is a child, not the value. You already have access to the value you want though, so I would use it like this:
<Tooltip key={risk.id} title={risk.name}>
<Tag
key={risk.id}
color={props.color}
onClick={() => props.onRiskClick(risk.id)}
>
{risk.id}
</Tag>
</Tooltip>
Then use it like this:
onRiskClick(value) {
console.log(value);
}
This will be a more flexible solution than accessing the innerHTML from the event target. You can now display it any way you want (or even render another component), and you function will still get the value it needs.
In this case, you already have the element, then to get the content inside the element you need to use e.target.innerHTML to get the tag content, other way is using e.target.textContent but is not supported on Firefox.
you should call e.persist() before console.log
If you want to access the event properties in an asynchronous way, you should call event.persist() on the event, which will remove the synthetic event from the pool and allow references to the event to be retained by user code.
Change your onclick function like this.you need to pass the event data to the function and use the data
const onRiskClick = e =>{
function ....
}
.....
<RenderingRiskMatrix
risks={this.state.risks}
impact="2"
likelihood="5"
color="red"
onRiskClick={e=>{
onRiskClick(e)
} <-- passing onRiskClick function as props
></RenderingRiskMatrix>
I found a solved issue about the "undefined" value from e.target.value
here
https://github.com/facebook/react/issues/4745
the solution was to use e.currentTarget.value instead
HTH.

Is render method of a component run in react-virtualized rowRenderer

I am using a List provided by react-virtualized. Inside the rowRenderer I return a more complex component. This component has some events defined for it. When an event is triggered, a part of the this component should be updated with new structure, e.g. a new input is rendered inside the row. This doesn't not seem to work when used inside the List.
<List height={height} width={1800} rowCount={this.state.leads.length} rowHeight={rowHeight} rowRenderer={this.rowRenderer} />
Here's the rowRenderer:
rowRenderer(props) {
let opacityvalue = 1
if (this.state.deleted.indexOf(props.index) >= 0) {
opacityvalue = 0.3
}
return (
<LeadItem {...props}
lead={this.state.leads[props.index]}
leadKey={props.index}
...
/>
)}
Here's the element that should show up when a specific event is triggered:
{self.props.lead.show ? <Selectize
queryfield={'tags'}
handleChange={(e) => this.props.updateLeadData(self.props.leadKey, 'tags', 'update', e)}
value={self.props.lead.tags}
create={false}
persist="false"
multiple
options={self.props.TAGS}
/> : <div>{taglist}</div>}
EDIT: Here's a simple example where I prove my point.
https://codesandbox.io/s/2o6v4my7pr
When user presses on the button, there must appear a new element inside the row.
UPDATE:
I see now that it's related to this:
https://github.com/bvaughn/react-virtualized#pure-components
I think you can achieve what you're trying to do by passing through this property to List as mentioned in the docs:
<List
{...otherListProps}
displayDiv={this.state.displayDiv}
/>

How to pass a function instead of string as a prop to a component

I'm really new to reactjs and I was looking for a simple way to change the color of a button depending on states. Basically I'm using reactstrap and I have a button, I want its color to be "secondary", "danger" or "primary" the Button tag works that way :
<Button color={String} />
I want to use a function to put a String in there. basically here is a small function :
buttonClassName(radioId) {
if (this.state.whatevs.valid === false)
return "danger";
if (this.state.whatevs.value === radioId)
return "primary";
return "secondary;
}
here is how I want to use it :
<Button outline color={() => this.buttonClassName(1)}>blah blah1</Button>
<Button outline color={() => this.buttonClassName(2)}>blah blah2</Button>
<Button outline color={() => this.buttonClassName(3)}>blah blah3</Button>
and so on for more buttons, problem is, react logically barks at me because :
Warning: Failed prop type: Invalid prop `color` of type `function` supplied to `Button`, expected `string`.
I agree with it, but how can I make that string change without passing a function, do I have to make state out of it, it seems so boringly circumvoluted. When I only had two states, I could just do something like that :
<Button outline color={(whatevs.valid === false)?"danger":"secondary"}>blah blah1</Button>
and that's not really a string either, but it worked.
You can most definetly use a function to return a string. The problem with your implementation is that you were passing a whole function by reference rather than the result of a function.
Just do this simple fix below. This will execute the function and return the desired string to the <Button> component.
<Button outline color={this.buttonClassName(1)}>blah blah1</Button>
<Button outline color={this.buttonClassName(2)}>blah blah2</Button>
<Button outline color={this.buttonClassName(3)}>blah blah3</Button>

React Bootstrap: set props on component dynamically

Due to a rather elaborate scenario I won't explain, I need to be able to set the placement prop on a React Bootstrap component dynamically when the user initiates the trigger. I was thinking something like this:
<OverlayTrigger
ref="trigger"
onEnter={onEnterFunc}
placement="bottom"
overlay={<Popover>...</Popover>}>
<span>html</span>
</OverlayTrigger>
Then in onEnterFunc somehow dynamically change the placement value. Anyone know if that's possible?
You can store the current value of placement in a parent component's state. You can specify an initial value in the component's constructor, and you can update this value by calling setState in your onEnterFunc function. Your updated markup/render function will look like this:
render() {
return (
<OverlayTrigger
ref="trigger"
onEnter={() => this.onEnterFunc()}
placement={this.state.placement}
overlay={<Popover>...</Popover>}>
<span>html</span>
</OverlayTrigger>
);
}

Resources