withNavigation on class component with typescript - reactjs

Please help me get this minimum-working example with withNavigation to work
https://codesandbox.io/s/withnavigation-not-working-lds560?file=/src/index.js
import React, {Component} from "react";
import {withNavigation, NavigationInjectedProps} from "react-navigation";
class App extends Component<NavigationInjectedProps> {
render() {
return <h1>Hello CodeSandbox</h1>;
}
}
export default withNavigation(App);

I found a little hacky-solution in which you create your own custom withNavigation. (I am still looking for a solution to make it work without having to create your own custom withNavigation function)
App.tsx
import React, {Component} from "react";
import {useNavigate, NavigateFunction} from "react-router-dom";
class App extends Component<{navigate: NavigateFunction, text: string}> {
render() {
return <button onClick={() => this.props.navigate("/c")}>
We are at path: {this.props.text}, navigate to "/c"
</button>;
}
}
function withNavigation(Component: any): (props: any) => JSX.Element {
return props => <Component {...props} navigate={useNavigate()} />;
}
export default withNavigation(App);
index.js
import * as ReactDOMClient from "react-dom/client";
import {Route, Routes, BrowserRouter } from "react-router-dom";
import App from "./App";
const rootElement = document.getElementById("root");
const root = ReactDOMClient.createRoot(rootElement);
root.render(
<BrowserRouter>
<Routes>
<Route path="/a" element={<App text={"a"}/>}/>
<Route path="/b" element={<App text={"b"}/>}/>
</Routes>
</BrowserRouter>
);

You need to move your
import {withNavigation, NavigationInjectedProps} from "react-navigation"
to a separate file which you have to include in App and wrap in in <Navigation Container>.
See here
Update:
I’ve just seen that you are trying to work with react-navigation 4! This probably won’t work with my solution but considering that version 4^ is no longer maintained, you might think about updating to version 5^.

Related

Route not taking the element HomePage from functional component / JSX element type does not have any construct or call signatures

Im having issues where the route wont take the element as is. Trying to use typescript for this project, and I'm running into this issue with vague results online, as I am also trying to use functional components mostly if possible.
The error in question: JSX element type 'HomePage' does not have any construct or call signatures.
I've already tried fixes like casting the page as a React.ElementType, but nothing is working so far and I'm just left puzzled.
Let me know if anything else is needed.
HomePage.tsx
import React, {useState, useEffect, ReactNode, ReactElement, FunctionComponent} from 'react';
import Carousel from 'react-bootstrap/Carousel';
import Holder from 'holderjs';
export interface IHomePageProps {}
const HomePageComponent: FunctionComponent<IHomePageProps> = (props) => {
const [carouselSlide, setCarouselSlide] = useState<number>(0);
const handleSelect = (selectedIndex: number, e: any) => {
setCarouselSlide(selectedIndex);
}
// component (un)mounting
useEffect(() => {
Holder.run();
});
return (
<React.Fragment>
<main className='container bg-dark text-white vh-min-100 h-auto flex flex-wrap'>
// content
</main>
</React.Fragment>
);
}
const HomePage = HomePageComponent as React.ElementType;
export default HomePage
App.tsx
import React, {useState, useEffect, ReactNode} from 'react';
import { BrowserRouter as Router, Routes as Switch, Route } from 'react-router-dom';
import 'bootstrap';
import '../node_modules/bootstrap/dist/css/bootstrap.css'
import './App.scss';
import SiteNavbar from './components/Navbar';
import HomePage from './pages';
function App() {
return (
<div>
<header>
<SiteNavbar/>
</header>
<Router>
<Switch>
<Route path="/" element={<HomePage/>}/>
</Switch>
</Router>
</div>
);
}
export default App;

Link of react-router-dom updates the URL without rendering the component

I'm using the react-router-dom Link component to manage my navigation but it doesn't work.
The Link changes the URL but doesn't render the component.
Here is a simple app describing my problem. I'm trying to use My App header as go home link:
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import React from 'react';
const Navigation = () => {
return (
<div>
<Link to="/events">
<h1>My Application</h1>
</Link>
</div>
);
};
const ConnectedNavigation = connect((state) => state)(Navigation);
export default ConnectedNavigation;
App.jsx code :
import React from 'react';
import { Provider } from 'react-redux';
import { store } from '../store/index';
import ConnectedDashboard from './Dashboard';
import ConnectedEventDetails from './EventDetails';
import { Router, Route } from 'react-router-dom';
import { history } from '../store/history';
import ConnectedNavigation from './Navigation';
export const Main = () => (
<Router history={history}>
<Provider store={store}>
<div>
<ConnectedNavigation />
<Route exact path="/events" render={() => <ConnectedDashboard />} />
<Route
exact
path="/event/:id"
//match prop is necessary in order to determine which event
//we are looking for
render={({ match }) => <ConnectedEventDetails match={match} />}
/>
</div>
</Provider>
</Router>
);
As you can see i added exact on my Routes to avoid any confusions
This problem comes from this line:
import { Router, Route } from 'react-router-dom';
The correct import is :
import { BrowserRouter as Router, Route } from 'react-router-dom';

Context and Provider not accessible via Modal

I do not control the modal components in my company. The I am using redux-toolkit so I am wondering if this is the issue. I have tried a few different iterations trying to get this to work and tried mimicing another app that it works with (standard redux app).
The below code is me trying to mimic the other app that has it working.
my index.js
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import 'proxima-nova/scss/proxima-nova.scss'
import './css/styles.scss';
import { configureStore, getDefaultMiddleware } from '#reduxjs/toolkit';
import { RcReducer } from './Store/RC/Events';
import { RcDataReducer } from './Store/RC/RcData';
const middleware = [...getDefaultMiddleware()];
export const ReduxStore = configureStore({
reducer: {
RcEvents: RcReducer,
RcData: RcDataReducer,
},
middleware,
});
ReactDOM.render(<App store={ReduxStore} />, document.getElementById('app'));
My app.tsx
import React, { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Switch, Route } from 'react-router-dom';
import Wrapper from './Components/Wrapper/Wrapper';
import './App.scss';
import Loader from './Components/Common/Loader/Loader';
import { Provider } from 'react-redux';
import StoreProvider from './Store/Store';
const Home = lazy(() => import('./Components/Pages/Home/Home'));
const RcDashboard = lazy(() => import('./Components/Pages/RC/RC'));
const EccDashboard = lazy(() => import('./Components/Pages/ECC/Dashboard/Dashboard'));
const App: React.FunctionComponent<{ store: any }> = ({ store }: { store: any }) => {
return (
<Provider store={store}>
<StoreProvider>
<Router>
<div id='root'>
<Wrapper>
<Suspense fallback={<Loader overlay={true} fullscreen={false} size='xl' />}>
<Switch>
<Route path='/' exact component={Home} />
<Route path='/rc' component={RcDashboard} />
<Route path='/ecc' exact component={EccDashboard} />
</Switch>
</Suspense>
</Wrapper>
</div>
</Router>
</StoreProvider>
</Provider>
);
};
export default App;
I am calling a component that is provided for use within my company. I personally do not have control over how this component acts. It is a modal. The modal does not just append itself to the component it is called in and automatically appends itself to the body tag.
For some reason the neither my context nor my redux store are showing up. I instead get this.
I am currently at a loss as to how I can get this working. I appreciate any help provided.
I would assume that that modal if somehow forwarding the context value, but probably only legacy context. So it might work with an older version or react-redux, but not with a current one.
You'll have to either use a Portal in the modal instead of creating a completely new ReactDOM instance (which is probably happening right now) or forward the current value to a new in the modal, like this
function YourComponent(){
const store = useStore()
return <Modal><Provider store={store}>whatEverGoesIntoYourModal</Provider></Modal>
}

React: Loadable is not working?

Hi I am new in react and I want to implement routing with Loadable, But Its not working Its showing blank page when either http://localhost:3000/user or http://localhost:3000/
Could you please correct me where I am doing wrong.
I am also getting-
Warning: Failed prop type: Invalid prop component of type string supplied to Route, expected function.
My codes are:
home.js
import React, { Component } from 'react';
import { Link} from 'react-router-dom';
class Home extends Component {
render() {
return (
<div>
<h1>Welcome to the Tornadoes Website!</h1>
<h5><Link to="/user">User</Link></h5>
</div>
);
}
}
export default Home;
user.js:
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
class User extends Component {
render() {
return (
<div>
<ul>
<li>6/5 # Evergreens</li>
<li>6/8 vs Kickers</li>
<li>6/14 # United</li>
<li><Link to="/">Home</Link></li>
</ul>
</div>
)
}
}
export default User;
App.js:
import React from 'react';
import { Router, Route, Switch } from 'react-router-dom';
import { history } from './helpers/history';
import Loadable from 'react-loadable';
import './App.css';
const Loading = () => <div> Loading... </div>;
const Home = Loadable({
loader: () => import('./components/home-component/home'),
loading: Loading
});
const User = Loadable({
loader: () => import('./components/user-component/user'),
loading: Loading
});
class App extends React.Component {
render() {
return (
<Router history={history}>
<Switch>
<Route exact path="/" component="Home" />
<Route path="/user" component="User" />
</Switch>
</Router>
);
}
}
export default App;
index.js:
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import registerServiceWorker from './registerServiceWorker';
import { BrowserRouter } from 'react-router-dom'
ReactDOM.render((
<BrowserRouter>
<App />
</BrowserRouter>
), document.getElementById('root'))
registerServiceWorker();
I see you are doing this: <Route exact path="/" component="Home" /> which should be <Route exact path="/" component={Home} /> since you want to use that variable, it's impossible to reference by String when he can't know which Component you want. I hope this helps
This looks to me like there is a isRequired propType that you have missed when calling your component. Can you post your components here as well?

ReactJS Router V4 history.push not working

I have upgraded to React Router V4 and now struggling with the history.push method.
I have an index.js file:
import React from "react";
import { render } from "react-dom";
import { BrowserRouter, Route } from 'react-router-dom';
import createBrowserHistory from 'history/createBrowserHistory';
const history = createBrowserHistory();
import { Main} from "./components/Main";
import { About } from "./components/About";
import { Cars} from "./components/Cars";
class App extends React.Component {
render() {
return (
<BrowserRouter history={history}>
<div>
<Route path={"/"} component={Main} />
<Route path={"/cars"} component={Cars}/>
<Route path={"/about"} component={About}/>
</div>
</BrowserRouter>
)
}
}
render(<App/>, window.document.getElementById("app"));
And then I have another file, where I added a simple to return to a certain page which looks like this:
import React from "react";
import createBrowserHistory from 'history/createBrowserHistory';
const history = createBrowserHistory();
export class Cars extends React.Component {
navigateBack() {
history.push('/')
}
render() {
return(
<div>
<h3>Overview of Cars</h3>
<p>Model: </p>
<button onClick={this.navigateBack} className="btn btn-primary">Back</button>
</div>
)
}
}
So, I cannot figure out whats going wrong here. When I click on the button, the URL changes to / but thats all. Is there someone who can help me out?
EDIT
I found out, that it works when I do this:
this.props.history.push('/home')
and
<button onClick={this.onNavigateHome.bind(this)}
but it seems wrong somehow??
when I do
this.context.history.push('/home')
I get Cannot read property 'context' of null but why?? Is my <BrowserRouter> setup wrong??
Anyway, thanks for the help :)
You have to import {withRouter} from 'react-router-dom' and export your class in this way
export default withRouter(Cars)
Try adding forceRefresh={true} to your BrowserRouter.
<BrowserRouter forceRefresh={true}>
With v4 you have to use this.context.history.push('/cart');
check out these posts for more insights:
How to push to History in React Router v4?
history.push not working when using BrowserRouter
Try to use history from props and ensure that your export is wrapped with withRouter.
Ex:
this.props.history.push('/test')
export default withRouter(TestComponent)

Resources