I am using google analytics in my react project and it doesn't show any active users even when I am online. I have tried different approaches that I found online but none seem to work. I have only tried it on localhost and not on a deployed website but I think it should still work.
Here is my code.
My app.js
import React, { Suspense, useEffect } from "react";
import "./App.css";
import IntroPage from "./containers/IntroPage/IntroPage";
import Layout from "./containers/Layout/Layout";
import { Switch, Route, Redirect, withRouter } from "react-router-dom";
import Spinner from "./Components/UI/Spinner/Spinner";
import ReactGA from "react-ga";
const Contact = React.lazy(() => import("./Components/Contact/Contact"));
const trackingId = "UA-171033255-1";
ReactGA.initialize(trackingId);
function App() {
useEffect(() => {
ReactGA.pageview(window.location.pathname + window.location.search);
}, []);
return (
<div className="App">
<Layout>
<Switch>
<Route
path="/contact"
render={() => (
<Suspense
fallback={
<div className="Fallback">
<Spinner />
</div>
}
>
<Contact />
</Suspense>
)}
/>
<Route path="/" component={IntroPage} />
<Redirect to="/" />
</Switch>
</Layout>
</div>
);
}
export default withRouter(App);
What am I doing wrong here?
Updating from react-ga to react-ga4 worked for me.
Change the import to react-ga4 and instead of ReactGA.pageview(...) use ReactGA.send("pageview").
Have you tried adding the tracking code inside <head> in index.html (Admin -> Property -> Tracking code)?
Since you are using empty dependencies array in useEffect your code gets executed only once, when <App/> rendered. So you are not sending pageviews on route change.
You need to put pageview-related code before your App component, right after ReactGA initialization. It's a usage example from docs.
I had a similar issue try disabling your ad block if you have it active and put the ReactGA.initialize inside the useEffect
import ReactGA from "react-ga4";
ReactGA.initialize("your measurement id");
ReactGA.send("pageview");
Related
Im new to this website so bear with me.
I'm developing an appointment based website in which I have a login page, a profile page, and a register page. Im trying to implement a programatic redirect to a users profile, I opted to use useNavigation from react-router-dom. I attempted to use the navigate function like the documentation says but it crashes my website after the render. I stepped through my code with my debugger and the correct page does render, however, somewhere after the render, my site goes blank and returns an error im confused by. I've managed to simplify/obfuscate my code aswell in the examples below.
This is the applicable code to my problem. When the page is rendered it will check for a JWT in local storage, it then verifies the JWT in my server and returns data, i expected that if the jwt is verified then the page will redirect to my profile page route. which it does do, but then goes blank.
The profilePage route is currently unprotected for simplicity so i can figure out why useNavigate isn't working.
index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { BrowserRouter } from "react-router-dom";
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<BrowserRouter>
<App />
</BrowserRouter>
</React.StrictMode>
);
app.js
import Appbar from './appbar.jsx';
import { Route, Routes } from 'react-router-dom';
import Login from "./components/login/login.jsx";
import ProfilePage from "./components/profilePage/profilePage.jsx";
export default function App() {
return (
<div className="App">
<Appbar/>
<>
<Routes>
<Route path="/" element={<Home /> }/>
<Route path="/login"/> element={<Login />}/>
<Route path="/profilePage" element={<ProfilePage />}/>
</Routes>
</>
</div>
);
}
login.jsx
import { useNavigate } from 'react-router-dom';
import { useEffect } from 'react';
export default function Login(props) {
const navigate = useNavigate()
/*
EDIT: I added this here because this was in my original code that got me my original error
*/
useEffect( async () => {
// My express route verifying the JWT
const response = await fetch('/users/userAuth', {
method: 'POST',
headers: {
'x-access-token': localStorage.getItem('token'),
},
})
const data = await response.json()
if (data.isLoggedIn === true)
{
navigate("/profilePage")
}
else {
console.log("not logged in")
}
}, [])
profilePage.jsx
export default function ProfilePage() {
// Keeping it simple until i can get useNavigate to work
return (
<div>
<h1>Profile Page</h1>
</div>
)
}
This is the error I get:
React Error from useNavigate
EDIT: Thanks for the patience regarding the edits. In an effort to obfuscate I removed the crucial parts of my code. Although im still getting the same error
in your code I think you forgot to define navigate
const navigate = useNavigate();
I think that the problem is on the async function passed in React.useEffect. You should create the async function inside React.useEffect's setup and then call it.
Have a look here on how to use async functions with React.useEffect
When ever i add a <Route> tag to the code everything just disappears from the screen!
the code is fine i guess! there is no warnings showing!!
the output before adding the <Route> tags
and when i add a <Route> tag the output is just not there anymore!!!!
the code before adding the tag:
import React from "react";
import "./App.css";
import Header from "./Header";
import { BrowserRouter, Route } from "react-router-dom";
function App() {
return (
<div className="App">
<BrowserRouter>
<Header />
</BrowserRouter>
</div>
);
}
export default App;
and the code after is really the same but with adding the tags :
import React from "react";
import "./App.css";
import Header from "./Header";
import { BrowserRouter, Route } from "react-router-dom";
function App() {
return (
<div className="App">
<BrowserRouter>
<Header />
<Route></Route>
</BrowserRouter>
</div>
);
}
export default App;
And when i added the tags the content disappeared !
Check you're package.json if the version of react-router-dom is 6 then downgrade it to 5 thats where error comes from.
I know this because now npm install install version 6 as its default version but the tutorials and knowledge about react router on line is still for version 5.
so on your package.json change version from 6 to 5.3.0 and run npm install on your terminal
Since the route tag is empty, you aren't returning anything. You need to pass the path and the component that should be rendered for each path.
In this case considering you have a single path and want to show Hello World!! when the app starts, you should add
<BrowserRouter>
<Route exact path="/" component={App} />
</BrowserRouter>
This will render your App component when you start the app. You can add other components for other routes similarly.
There are few things to do :
a) in react-router-dom v6 Route element should be inside Routes element.
b) instead of component attribute you will have element attribute
c) element attribute should contain jsx like below
<Routes>
<Route exact path="/" element={
<>
<SomeComponent></SomeComponent>
<SomeOtherComponent></SomeOtherComponent>
</>
}>
</Route>
<Route path='/other_address' element={<OtherComponent />}></Route>
</Routes>
I'm learning react and got stuck at react-routes
consider the following:
import React from "react";
import { BrowserRouter, Route, Switch } from "react-router-dom";
import HelloWorld from "./HelloWorld.jsx";
const Root = () => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path="/" exact component={HelloWorld} />
<Route component={NoMatch} />
</Switch>
</div>
</BrowserRouter>
);
};
function NoMatch({ location }) {
return (
<div>
<h3>
No match found
</h3>
</div>
);
}
export default Root;
on '/' this route, it renders HelloWorld component as expected but on other routes for examples abc it displays Cannot GET /abc instead of No match found
This happens because your server is not set up to handle those routes specifically. The server it what determines what exists and what doesn't - react-router is just a tool to exploit it a bit.
Fix 1
You can avoid this issue by importing HashRouter from the react-router-dom package, rather than BrowserRouter.
The result will be routing based on URLs with a #/ prepending the route itself. So your route of / will now actually be #/.
Fix 2
Set up a reverse proxy (nginx) as the intermediary to serve your page from the Node.js server. Use a broad wildcard or get specific if you know you need more specific configurations. It will pass along the request URI/path to node still but not try to use them as separate endpoints each time or read files from the file system.
First you check your react version then after do like this if v5.1 and above
In order to use v6, you'll need to convert all your elements to <Routes>
You want to replace component to element into <Route ...>
example:- App.js
import Home from "./Home";
import About from "./About";
import {BrowserRouter as Router, Route, Routes } from "react-router-dom";
function App() {
return (
<Router>
<Routes>
<Route exact path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</Router>
);
}
export default App;
after that your switch related error maybe gone!
if still not working comment me i will help you
The code works just fine if you used create-react-app for setting up the react project but if you're using webpack configurations for manually setting up the project it requires devServer: {historyApiFallback: true,} for react routes to work.
Have a look into the sandbox it will help you:
https://codesandbox.io/s/py114mqzj0
Please upgrade your dependencies as follows:
"dependencies": {
"react": "16.5.2",
"react-dom": "16.5.2",
"react-router-dom": "4.3.1",
},
This seems to be working fine for me with latest React and react-router-dom.
import { BrowserRouter, Route, Switch } from 'react-router-dom';
const HelloWorld = () => {
return <div>Hello World</div>;
};
const Root = () => {
return (
<BrowserRouter>
<div>
<Switch>
<Route path='/' exact component={HelloWorld} />
<Route component={NoMatch} />
</Switch>
</div>
</BrowserRouter>
);
};
function NoMatch() {
return (
<div>
<h3>No match found</h3>
</div>
);
}
export default Root;
Code sandbox link to try it out
I'm migrating a site in ASP.NET MVC to REACT. And for pagination i have created a component in React.
Issue i'm facing is with Routing for the pagination URLs. React Router is not able to detect that the URL is different when i click on a pagination URL
Let me explain:
app.js code:
import React from 'react';
import ReactDOM from 'react-dom';
import {createStore, applyMiddleware} from 'redux';
import allReducers from '../reducers/index';
import {Provider} from 'react-redux';
import ReduxPromiseMiddleware from 'redux-promise';
import { BrowserRouter, Route } from 'react-router-dom';
import Main from './main';
import Layout from './layout';
const app = document.getElementById('root');
const store = createStore(allReducers, applyMiddleware(ReduxPromiseMiddleware));
ReactDOM.render(<Provider store={store}>
<BrowserRouter>
<Layout>
<Main/>
</Layout>
</BrowserRouter>
</Provider>
,app);
Main component render:
render(){
return(
<main>
<Switch>
<Route exact path='/' component={HomePage}/>
<Route path='/posts' component={PostsRouter} />
<Route path='/studies' component={StudiesPage} />
</Switch>
</main>
);
}
PostsRouter component:
const PostsRouter = () => (
<Switch>
<Route exact path='/posts' component={PostsPage} />
<Route path='/posts/:page' component={PostsPage} />
</Switch>
);
For both /posts and /posts/2 i need the component to be PostsPage.
Lets say i'm at /home. Now i click a posts link and URL changes to /posts. Now if i click /posts/2 link, nothing happens. React Router doesn't detect that the URL is different.
And a weird thing i noted is that if i change the component:
<Route path='/posts/:page' component={PostsPage} />
to
<Route path='/posts/:page' component={StudiesPage} />
then React Router routes me to StudiesPage component if i click on /posts/2 link when i'm on /posts URL.
May be i'm missing something obvious. But i haven't been able to figure out a way after lots of attempts.
I suspect Sergey's comment was right, that's what my problem ended up being. I was fetching data within componentDidMount() but didn't realise that in order to actually update it with new data when the next page link was clicked, I needed to do the same thing inside componentWillReceiveProps(). You can see my full source here but the biggest key part was this:
componentWillReceiveProps(nextProps) {
this.setState({
loaded: false
});
this.fetchMediaItems(nextProps.match.params.page);
}
componentDidMount() {
this.fetchMediaItems(this.props.match.params.page);
}
componentWillReceiveProps() receives the new properties, including page number, when you click on the link to page 2, so you need to do whatever inside there to update with the new state.
I'm trying to route programatically using this.props.history.push(..) but it doesn't seem to work.
Here's the router:
import {
BrowserRouter as Router,
Route
} from 'react-router-dom';
<Router>
<Route path="/customers/" exact component={CustomersList} />
<Route path="/customers/:id" exact component="{Customer} />
</Router>
In CustomerList, a list of customers is rendered. Clicking on a customer (li) should make the application route to Customer:
import { withRouter } from 'react-router'
class Customers extends Component {
static propTypes = {
history: PropTypes.object.isRequired
}
handleCustomerClick(customer) {
this.props.history.push(`/customers/${customer.id}`);
}
render() {
return(
<ul>
{ this.props.customers.map((c) =>
<li onClick={() => this.handleCustomerClick(c)} key={c.id}>
{c.name}
</li>
</ul>
)
}
}
//connect to redux to get customers
CustomersList = withRouter(CustomersList);
export default CustomersList;
The code is partial but illustrates perfectly the situation.
What happens is that the browser's address bar changes accordingly to history.push(..), but the view does not update, Customer component is not rendered and CustomersList is still there. Any ideas?
So I came to this question hoping for an answer but to no avail. I have used
const { history } = this.props;
history.push("/thePath")
In the same project and it worked as expected.
Upon further experimentation and some comparing and contrasting, I realized that this code will not run if it is called within the nested component. Therefore only the rendered page component can call this function for it to work properly.
Find Working Sandbox here
history: v4.7.2
react: v16.0.0
react-dom: v16.0.0
react-router-dom:
v4.2.2
It seems things have changed around a bit in the latest version of react router. You can now access history via the context. this.context.history.push('/path')
Also see the replies to the this github issue: https://github.com/ReactTraining/react-router/issues/4059
You can try to load the child component with history. to do so, pass 'history' through props. Something like that:
return (
<div>
<Login history={this.props.history} />
<br/>
<Register/>
</div>
)
For me (react-router v4, react v16) the problem was that I had the navigation component all right:
import { Link, withRouter } from 'react-router-dom'
class MainMenu extends Component {
render() {
return (
...
<NavLink to="/contact">Contact</NavLink>
...
);
}
}
export default withRouter(MainMenu);
Both using either
to="/contact"
or
OnClick={() => this.props.history.push('/contact')};
The behavior was still the same - the URL in browser changed but wrong components were rendered, the router was called with the same old URL.
The culprit was in the router definition. I had to move the MainMenu component as a child of the Router component!
// wrong placement of the component that calls the router
<MainMenu history={this.props.history} />
<Router>
<div>
// this is the right place for the component!
<MainMenu history={this.props.history} />
<Route path="/" exact component={MainPage} />
<Route path="/contact/" component={MainPage} />
</div>
</Router>
You can get access to the history object's properties and the closest 's match via the withRouter higher-order component. withRouter will pass updated match, location, and history props to the wrapped component whenever it renders.
import React, { Component } from 'react'
import { withRouter } from 'react-router';
// you can also import "withRouter" from 'react-router-dom';
class Example extends Component {
render() {
const { match, location, history } = this.props
return (
<div>
<div>You are now at {location.pathname}</div>
<button onClick={() => history.push('/')}>{'Home'}</button>
</div>
)
}
}
export default withRouter(Example)
Seems like an old question but still relevant.
I think it is a blocked update issue.
The main problem is the new URL (route) is supposed to be rendered by the same component(Costumers) as you are currently in (current URL).
So solution is rather simple, make the window url as a prop, so react has a chance to detect the prop change (therefore the url change), and act accordingly.
A nice usecase described in the official react blog called Recommendation: Fully uncontrolled component with a key.
So the solution is to change from
render() {
return(
<ul>
to
render() {
return(
<ul key={this.props.location.pathname}>
So whenever the location changed by react-router, the component got scrapped (by react) and a new one gets initiated with the right values (by react).
Oh, and pass the location as prop to the component(Costumers) where the redirect will happen if it is not passed already.
Hope it helps someone.
I had similar symptoms, but my problem was that I was nesting BrowserRouter
Do not nest BrowserRouter, because the history object will refer to the nearest BrowserRouter parent. So when you do a history.push(targeturl) and that targeturl it's not in that particular BrowserRouter it won't match any of it's route, so it will not load any sub-component.
Solution
Nest the Switch without wrapping it with a BrowserRouter
Example
Let's consider this App.js file
<BrowserRouter>
<Switch>
<Route exact path="/nestedrouter" component={NestedRouter} />
<Route exact path="/target" component={Target} />
</Switch>
</BrowserRouter>
Instead of doing this in the NestedRouter.js file
<BrowserRouter>
<Switch>
<Route exact path="/nestedrouter/" component={NestedRouter} />
<Route exact path="/nestedrouter/subroute" component={SubRoute} />
</Switch>
</BrowserRouter>
Simply remove the BrowserRouter from NestedRouter.js file
<Switch>
<Route exact path="/nestedrouter/" component={NestedRouter} />
<Route exact path="/nestedrouter/subroute" component={SubRoute} />
</Switch>
Let's consider this scenario. You have App.jsx as the root file for you ReactJS SPA. In it your render() looks similar to this:
<Switch>
<Route path="/comp" component={MyComponent} />
</Switch>
then, you should be able to use this.props.history inside MyComponent without a problem. Let's say you are rendering MySecondComponent inside MyComponent, in that case you need to call it in such manner:
<MySecondComponent {...props} />
which will pass the props from MyComponent down to MySecondComponent, thus making this.props.history available in MySecondComponent
You need to export the Customers Component not the CustomerList.
CustomersList = withRouter(Customers);
export default CustomersList;
I see that you are using a class component but in case you decide to switch to functional component or encountered the same issue with a functional component in your application, you can fix this issue by using the "useHistory" hook API by react-router-dom.
Example of usage:
import { useHistory } from "react-router-dom";
const Customers = ({customer}) => {
let history = useHistory();
const handleCustomerClick = (customer) => {
history.push(`/customers/${customer.id}`);
}
return (
//some JSX here
);
};
You may find the official documentation here: https://reactrouter.com/web/api/Hooks/usehistory
Beginner's mistake when working with routing is the importance of using withRouter directly with the component and not put any other high order component in between (or at least one that doest not know to push the props.history to its children:
Wrong: export default withRouter(withErrorHandler(Foo));
Correct: export default withErrorHandler(withRouter(Foo));
`const navigate=useNavigate();
navigate(/customers/${customer.id}); `
Don't use with Router.
handleSubmit(e){
e.preventDefault();
this.props.form.validateFieldsAndScroll((err,values)=>{
if(!err){
this.setState({
visible:false
});
this.props.form.resetFields();
console.log(values.username);
const path = '/list/';
this.props.history.push(path);
}
})
}
It works well.
You need to bind handleCustomerClick:
class Customers extends Component {
constructor() {
super();
this.handleCustomerClick = this.handleCustomerClick(this)
}
this.props.history.push(`/customers/${customer.id}`, null);