How to fire onSelectStart in React/JSX? - reactjs

I'm familiar with the usage of selectstart event in HTML. I'm using onSelectStart in JSX. I expect it connects to onselectstart. But, it throws a warning saying that it's unknown.
Warning: Unknown event handler property `onSelectStart`. It will be ignored.
Example code:
function Example() {
return (
<div className="Example">
<h2 onSelectStart={() => console.log("Selection started")}>Click</h2>
</div>
);
}
I've tried this with react/react-dom#16.8.4 and react-scripts#3.0.1.
Is there an alternative for onSelectStart? If yes, how to implement the same?

Apparently https://reactjs.org/docs/events.html#selection-events not supported by react it seems. Even on MDN docs this dont seem to be standardized event: https://developer.mozilla.org/en-US/docs/Web/API/Document/selectstart_event#Specifications so I would question validity of its usage.
Here's the workaround using refs:
https://codesandbox.io/s/fancy-wave-sotun
ref={el => {
el &&
el.addEventListener("selectstart", () => {
console.log("Selection started");
});
}}
Just dont forget to remove Event listener on unmount of component.

Related

React with typescript, button function doesn't work

I'm slowly starting to learn TS and implement it to current project however I stuck and don't really understand what is wrong. Basically I have button which has dataset "mode". After clicking on button I launch confirm bar (confirm bar is not TSX yet)
<Button
height={50}
data-mode="MEMORY"
onClick={(e: React.MouseEvent<HTMLButtonElement>) =>
ConfirmBar('You sure?', supportCommands, e)
}
>
Format
</Button>
const ConfirmBar = (message, action, parameter) =>
confirmAlert({
customUI: ({ onClose }) => {
return (
<ConfirmContainer>
<Header main>{message}</Header>
<ConfirmationButton
confirm
onClick={() => {
action(parameter);
onClose();
}}
>
Yes
</ConfirmationButton>
<ConfirmationButton onClick={onClose}>No</ConfirmationButton>
</ConfirmContainer>
);
},
});
In case of yes I wish to launch function to proceed request, it worked correctly before typescript but now it throws error. I wish to get access to dataset attribute and would be glad if you guys help me and explain me why it doesn't want to work now after added typescript
const supportCommands = (el: React.MouseEvent<HTMLButtonElement>) => {
// Tried already to use el.persist(), with target and currentTarget; here is example with attempting to assign value to variable but also doesn't work.
const target = el.currentTarget as HTMLButtonElement;
let elVal = target.getAttribute('data-mode');
console.log(elVal, 'ELL');
};
And that's the error I occur:
Warning: This synthetic event is reused for performance reasons. If
you're seeing this, you're accessing the method currentTarget on a
released/nullified synthetic event. This is a no-op function. If you
must keep the original synthetic event around, use event.persist().
See fb.me/react-event-pooling for more information.
I understand that React has own system of SynthesisEvents but I thought they cause problems during asynchronous requests like with timers etc, in this situation I see no reason why it makes problem
EDIT: I made it work by adding to button e.currentTarget, and then in function just did el.dataset, now just trying to figure out what kind of type is that
This waring is because you are reusing Event object.
You passed it here ConfirmBar('You sure?', supportCommands, e)
And you reused it here action(parameter);
I don't know what do you need from paramenter but I guess it could be like this:
onClick={(e) => {
action(e);
onClose();
}}
I have never needed to use event of onClick. The only idea I can imagine is for preventDefault or stopPropagation

Using refs to modify an element in React.js

Is it wrong to use refs to modify an element's properties? If so, why?
Example:
myRef.current.innerHTML = "Some content";
That's wrong if it's possible to modify the component's JSX to implement the change instead. Whenever possible, one should be able to determine the JSX that gets rendered solely from the current state of the component; direct DOM mutation side-effects like .innerHTML should only be done when there's no other possible option.
For this case, put the content into a state variable instead, like:
const [spanContents, setSpanContents] = useState('foobar');
const changeSpanContents = () => {
setSpanContents('Some content');
};
return (
<div>
<button onClick={changeSpanContents}>click</button>
<span>{spanContents}</span>
</div>
);
In some unusual cases, there exists no JSX syntax for the DOM mutation you want - for example, for putting a resize listener on the window. In such a case, you will have to resort to using vanilla DOM methods instead of doing it solely through React. The following pattern is common for such a case:
useEffect(() => {
const handler = () => {
// resize detected
};
window.addEventListener('resize', handler);
return () => {
window.removeEventListener('resize', handler);
};
}, []);
I wouldn't say wrong but it depends on what you are going to do after changing the html. As React will loose control over that element, you would have a hard time if you need to work on that DOM. Also, it is risky because React have controls over DOM, when you change it manually, it could lead to unexpected behaviors.

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.

Understanding React refs - why is my reference null here?

I have a use-case where a React ref makes sense.
I've tried a few different ways of implementing them, and in this case integrating them with hammerjs.
I'm mostly going off of this question:
adding hammerjs to a react js component properly
My return method in my render is as such:
return (
<div className={"App card-row card-color " + this.props.className} ref={
(el) => this._slider = el
}>
{this.state.bubblemsg ? (
<NotifBubble message={this.state.bubblemsg} merchant={this.props.merchant.merchant}/>
) : (
null
)}
<ScrollMenu
data={this.state.list}
inertiaScrolling={true}
transition={.1}
inertiaScrollingSlowdown={.000001}
/>
</div>
);
Which I would think would attach my div element as a reference.
In my componentDidMount() method, I am then attaching it to hammer:
componentDidMount() {
this.hammer = Hammer(this._slider)
this.hammer.on('swipeleft', console.log("swipe left"));
this.hammer.on('swiperight', console.log("swipe right"));
}
However, I am getting the error:
TypeError: Cannot read property 'addEventListener' of undefined
And this is directly related to Hammer, and thus the reference I assume.
So what am I doing wrong with my references? I don't totally understand how they're supposed to work and the React tutorial explanation wasn't super clear, so a thorough explanation would be useful.
I think the problem is that in the listening of the hammer you have to pass a function to be called, try inserting an arrow function to log
componentDidMount() {
this.hammer = Hammer(this._slider)
this.hammer.on('swipeleft', () => console.log("swipe left"));
this.hammer.on('swiperight', () => console.log("swipe right"));
}

Can't bind anything: "Cannot call method "bind" of undefined"

import React from 'react'
const Buttons = React.createClass({
getInitialState() {
return {clicks: 0}
},
countClicks() {
this.setState({
clicks: ++this.state.clicks
})
console.log(this.state.clicks)
}
render() {
return (
<div>
<div onClick={console.log("HEYYY")}>This should log "HEYYY"</div>
<div onClick=({this.countClicks()}>This should update clicks</div>
)
}
})
This will print "HEYYY" and 1 respectively on the first render but never do anything when actually clicked.
While this gave me some headache I found the solution in an example:
//Instead of doing this
<a onClick={this._changeValue(2)}>Change Value</a>
//Do this
<a onClick={this._changeValue.bind(2)}>Change Value</a>
Ah, perfect, I thought. Except that when I try it I get an error:
TypeError: Cannot call method 'bind' of undefined
I removed the simple console.log because I have no idea what to bind in it and went with countClicks() only, and I did get it somewhat working when I removed the parenthesis like so:
<div onClick=({this.countClicks.bind(this)})>This should update clicks</div>
First of all, why can't I bind something when I have the parenthesis in? Second, I instead got an ugly WARNING:
Warning: bind(): You are binding a component method to the component.
React does this for you automatically in a high-performance way, so
you can safely remove this call.
Is React stupid?!
Or am I..?
My own solution:
render() {
const self = this
<div onClick={function() { self.countClicks() }}>This should update clicks</div>
}
No use of bind, no errors, no warnings.

Resources