React - onclick function is running on page load - reactjs

the code in the file is simple. it is imported into another file that places it in a slider container. That all works I'm just having trouble with the onClick function running on page load instead of on click.
import React from 'react';
import M_IMAGE from 'assets/image.png';
function openImage() {
window.open(M_IMAGE);
}
export const slider = {
data: [
{
content: (
<img src={M_IMAGE} onClick="openImage" />
)
}
]
}
I have tried this.openImage.bind and many other variants I have seen online.

You are missing the curly braces around the onClick's event handler and need to assign it like below:
<img src={M_IMAGE} onClick={openImage}

UKS commented on the post with an response leading to the fix.
I had to delete the function because it existing caused it to run on load and change the code to
<img src={M_IMAGE} onClick={()=> window.open(M_IMAGE)} />

Related

how do I interpolate a Link component in Next-i18next / React i18next that changes position in the text

Currently I'm using Next.js with Next-i18next for I18N, but I understand that the React/i18next implementation is basically the same.
The problem I'm having is that I need to interpolate a next Link component inside some translation text, but depending on the language (English vs German), the order of the text and the link would change.
For instance the text I'm struggling with is: 'Accept data policy' vs 'Datenschutzerklärung akzeptieren'
As of the moment I have a quick fix by creating two values in the translation JSON files for the text and the link and then swapping the position based on the current language. Obviously this is not a sustainable solution. I have tried to utilise the 'Trans' component but this is showing some unexpected behaviour where the translation only kicks in after the page is refreshed, otherwise you see the text inside the Trans component.
example:
function LinkText({ href, children}) {
return <Link to={href || ''}>{children}</Link>;
}
return (
<Trans i18nKey="sentence">
text before link
<LinkText href="/data-policy">{t("dataPolicy")}</LinkText>
text after link
</Trans>
);
and the JSON in question:
{
"sentence": "agree to our <1><0/></1>",
"dataPolicy": "data policy"
}
Here's a link to CodeSandbox I made to replicate the problem with in React: link
(P.S The implementation of i18next doesn't seem to effectively swap out the languages in Codesandbox at the moment, but I included it as the code is there for a MWE)
Thanks in advance for your help, this has been driving me insane.
You had few missing parts,
Your i18next config was lack of a way to fetch the locale files, I've added i18next-http-backend.
You should use Trans component to inject the link to the sentence.
Your locale json should look like this:
{
"sentence": "Accept <0>data policy</0>"
}
// TranslatedLink.js
import React from 'react';
import { useTranslation, Trans } from 'react-i18next';
import { Link } from 'react-router-dom';
function LinkText({ href, children }) {
return <Link to={href || ''}>{children}</Link>;
}
export default function TranslatedLink() {
const { t } = useTranslation(['common']);
return (
<div style={{ padding: 50 }}>
<Trans i18nKey="sentence" t={t} components={[<LinkText href="/data-policy" />]} />
</div>
);
}
A working example: https://codesandbox.io/s/react-i18n-interpolation-issue-forked-ck8l4

reactJS adding an event listener to a navbar tile

I am running the current version of reactJS with hooks. I have three code modules in my app: header.js which creates a navbar and exports it to app.js which adds some other objects and exports all of this to index.js.
I am trying to add an event listener to the individual tiles in the navbar so that I can redirect to the appropriate page.
code
var listenerElement = document.getElementById("Tile1");
if (listenerElement !== null) {
listenerElement.addEventListener("click", navbarClicked) ;
console.log(listenerElement);
} else {
console.log("Element with ID=Tile1 not found");
}
<div id="Tile1" className="linkcontainer">Home</div>
/code
However, I cannot find an appropriate place to add the event-listener and the element with ID "Tile1" is never found - perhaps because it hasn't been rendered as yet?
The element in question is only rendered by index.js but I can't add a function after the reactDOM.render block in index.js - I get an error "not a react function"
Any suggestions would be much appreciated :-)
For react, you should use "refs" to link to a specific aspect of the navabar.
But as you are just trying to have something affect the navbar, you should use the "onClick" property for the div or iconButton or similar.
for example in a function component:
function handleClick() {
console.log("clicked");}
<nav> <iconButton onClick={handleClick} > button </iconButton> </nav>
https://reactjs.org/docs/handling-events.html
In react, you don't work with the DOM directly. React makes a copy of the DOM called virtual DOM and then compares them to update the DOM. You should add your event listener using props.
So instead of:
document.getElementById("Tile1").addEventListener("click", navbarClicked);
you should do <div onClick={navbarClicked} id="Tile1" className="linkcontainer">Home</div>

How can I change a source of a video in react?

I have used a react-video component in my reactjs web application and it's working with a default source link, but when I'm using my video as a source, nothing happens.
I have searched a lot, read the documentation about react-video component, but could not solve the problem.
import {Player} from 'video-react';
<div className = 'video-container'>
<Player
playsInline
fluid={false}
src="https://media.w3.org/2010/05/sintel/trailer_hd.mp4"
width={600}
height={300}/>
</div>
I expect the new source to be working without any issues, but it never starts playing.
#Dato.Beriashvili, I have faced similar issues in default html video API, whenever i change src by anymeans video was not updated. so i have done below which fixed my issue.
useEffect(() => {
const myVideo= innerDoc.querySelector('#videoPlayer');
const mySource = innerDoc.querySelector('#source');
if (mySource && myVideo) {
mySource.setAttribute('src', videoUrl);
myVideo.load();
}
}, [videoUrl]);
whenever url changed, i'm manually loading it.

Link in Infobox using react-google-maps causes page reload

I'm not able to put a react-router-dom Link inside of a react-google-maps InfoBox without causing a full page reload.
Here's the code for my InfoBox:
import InfoBox from 'react-google-maps/lib/components/addons/InfoBox'
import { Link } from "react-router-dom";
class MyInfoBox extends Component {
...
const options = {
enableEventPropagation:false,
position: new google.maps.LatLng(loc.latitude, loc.longitude)
};
render(){
return (
<InfoBox options={options}>
<Link to={`/location/${loc.id}`}>Go To Location</Link>
</InfoBox>
);
}
}
All Links in my app work correctly, except for this one.
When the "Go To Location" link is clicked, a full-page reload is caused. I've tried to diagnose by following this issue: https://github.com/tomchentw/react-google-maps/issues/258, but I really don't know enough about the react router v4 to find out if the context contains the router object. Changing the value of enableEventPropagation does not change the behavior.
If anyone can help me understand why the Link is causing a page reload, I would really appreciate it.
Thank you in advance!
Try removing onClick prop in <GoogleMap> component and add enableEventPropagation: true to <InfoBox> options.
For me the issue was that <GoogleMap> onClick event was used to remove <InfoBox> when user clicks outside it. But turns out it is called also inside <InfoBox> so basically it was removing <InfoBox> with the <Link> inside it, before handling <Link> click.

onClick not being called ReactJS

Before downvoting, I've been through plenty of other solutions on SO around this same issue and can't find an answer that resolves this issue.
I'm having trouble trying to get the onClick attribute to fire off my function, here's a piece from the problematic component:
Constructor:
constructor() {
super();
this.state = {
submissionFormCount: 0
}
this.addToSubmissionFormCount = this.addToSubmissionFormCount.bind(this);
}
render:
<div className="row">
<div className="col s12 m12 l12">
<h5 onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</h5>
</div>
</div>
clickHandler:
addToSubmissionFormCount() {
alert('Here');
this.setState({
submissionFormCount: this.state.submissionFormCount++
});
}
I'm rendering the app from an Express server using 'react-dom/server'
Here's how I am rendering the component:
exports.beatSubmission = (req, res) => {
const appString = renderToString(<App type="beatSubmission"/>);
res.send(beatSubmissionTemplate({
body: appString
}))
}
I think you're only rendering your react components on the server side. The reason I think this is because of the following code you've copied:
exports.beatSubmission = (req, res) => {
const appString = renderToString(<App type="beatSubmission"/>);
res.send(beatSubmissionTemplate({
body: appString
}))
}
You're rendering the component to a string and shipping the string to the frontend as static HTML. While this will indeed give you properly rendered markup, it will result in a non-interactive app.
To have click handlers work, you also need to compile your JS, and include it for use on the frontend like this:
https://github.com/erikras/react-redux-universal-hot-example/blob/master/src/server.js#L76
renderToString(<Html assets={webpackIsomorphicTools.assets()} store={store}/>));
There are a few ways to do this. You can manually add a script file with your JS pre-packaged for the frontend in your template or you can use Webpack Isomorphic Tools.
I suspect you read a react tutorial that lead you down the isomorphic (server/client side rendered) path. You can run react on the server, the client side or both. Running it on both takes some work, but results in an app that "feels" faster.
I can't see any problem with the code. However, the only thing that comes to my mind is if you're rendering the <h5> in a function of some sort, maybe mapping and array for example. If so, you need to define var self = this in the render function before the return, then use self.addToSubmissionFormCount.
P.S. I don't recommend using onClick handler in <h5> tag
Change your h5 into an anchor tag. So replace:
<h5 onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</h5>
with:
<a onClick={this.addToSubmissionFormCount} style={beatSubmissionStyles.colorize}><span>(Plus) </span>add another beat</a>
You can style your anchor anyway you want afterwards. For example if you want to not have a cursor when hovering then add cursor: none
You should not mutate the state of react.
Change:
this.state.submissionFormCount++
To:
this.state.submissionFormCount+1

Resources