React Redux routing issues - javascript

I have recently experienced some issues with my react router and redux. Basically, I have a redux value set which let's me know if an item is selected. If the item is selected, then it will allow a URL to be used. One thing that I have noticed. If I add a redirect function. It breaks everything
Authentication function:
import React, { Component, Fragment } from "react";
import { Provider } from "react-redux";
// import store from "./store";
import {
BrowserRouter as Router,
Switch,
Route,
Redirect
} from "react-router-dom";
import { connect } from "react-redux";
import Profile from "./Profile";
import AddDomain from "./AddDomain";
import ChoosePackage from "./ChoosePackage";
import DashboardHome from "./DashboardHome";
import { Elements } from "#stripe/react-stripe-js";
import PropTypes from "prop-types";
import { loadStripe } from "#stripe/stripe-js";
const stripePromise = loadStripe("pk_test_7S0QSNizCdsJdm9yYEoRKSul00z4Pl6qK6");
class index extends Component {
componentDidMount() {
console.log("DOMAIN NAME" + this.props.domain_name);
}
state = {
domain_name: ""
};
static propTypes = {
domain_name: PropTypes.string.isRequired
};
domainCheck = () => {
if (this.props.domain_name != "") {
return <ChoosePackage />;
} else {
console.log("running rediect");
return <Redirect to="/dashboard" />;
}
};
render() {
return (
<React.Fragment>
<Route path="/dashboard/add-domain/choose-package">
{this.domainCheck()}
</Route>
<Route exact path="/dashboard/add-domain">
<AddDomain />
</Route>
<Route exact path="/dashboard/profile">
<Profile />
</Route>
<Route exact path="/dashboard">
<DashboardHome />
</Route>
</React.Fragment>
);
}
}
const mapStateToProps = state => ({
domain_name: state.domain.domain_name
});
index.defaultProps = {
domain_name: ""
};
export default connect(mapStateToProps, { pure: false })(index);
Any help is greatly appreciated

Related

reactjs redux - user is null

I dont know why when i try to fetch data from api using redux (i can see the data in when i mapstatetoprops ) but this error (user is null ) message show up when i try to display data to user.
this is a screenshot shown the user is null error
I call the dispatch from componentDidMount react, i think its the right place to call api,
this is my code :
import React, { Component } from 'react';
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";
import { connect } from 'react-redux';
import store from './state/store';
import { loadUser } from './state/actions/auth/authActions';
//pages
import Login from './app/auth/Login';
import Wrapper from './wrapper/Wrapper';
class App extends Component {
componentDidMount() {
store.dispatch(loadUser());
}
render() {
const { token, user, isLoading } = this.props.auth
return (
<Router>
<Routes>
<Route path='/login' element={<Login />} />
<Route path='/' element={token ? <Wrapper user={user._id} isLoading={isLoading}></Wrapper> : <Login />} />
</Routes>
</Router>
)
}
}
const mapStateToProps = state => {
return {
auth: state.auth
}
}
export default connect(mapStateToProps, { loadUser })(App);

Problems to match classes based on route in React

I've got a problem with assigning a class to the variable and then to the div based on his routing. I don't know what am I doing wrong, everything seems to be ok so where is the mistake then? I'm super curious about what did I do wrong.
import React from 'react'
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import { useLocation } from "react-router-dom";
import { useEffect } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import About from './About'
import Home from './Home'
const useStyles = makeStyles({
home: {
background: 'white',
},
about: {
background: 'black',
}
});
const App = () => {
const classes = useStyles();
let location = useLocation();
let style;
useEffect(() => {
style = classes.home
handleLocation()
console.log('.')
}, [location])
const handleLocation = () => {
if (location.pathname === "/") {
style = classes.home
} else if (location.pathname === '/about') {
style = classes.about
}
}
return (
<div className={style}>
<Router>
<Switch>
<Route path="/" exact>
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
</Router>
</div>
)
}
export default App
If something is unclear feel free to ask :)
try this code :
import React from 'react'
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import { useLocation } from "react-router-dom";
import { useEffect } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import About from './About'
import Home from './Home'
const useStyles = makeStyles({
home: {
background: 'white',
},
about: {
background: 'black',
}
});
const App = () => {
const classes = useStyles();
let location = useLocation();
const handleLocation = () => {
if (location.pathname === "/") {
return classes.home
} else if (location.pathname === '/about') {
return classes.about
}else if(more if you want){
return more class ....
}
}
return (
<div className={handleLocation()}>
<Router>
<Switch>
<Route path="/" exact>
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
</Router>
</div>
)
}
export default App
React's components re-renders when a state or a prop change, so the style variable is neither a state nor a prop, Now when you update it, UI doesn't change because the component doesn't re-render
import React from 'react'
import {
BrowserRouter as Router,
Switch,
Route,
Link
} from "react-router-dom";
import { useLocation } from "react-router-dom";
import { useEffect } from 'react';
import { makeStyles } from '#material-ui/core/styles';
import About from './About'
import Home from './Home'
const useStyles = makeStyles({
home: {
background: 'white',
},
about: {
background: 'black',
}
});
const App = () => {
const classes = useStyles();
let location = useLocation();
return (
<div className={ location.pathname === "/" ? classes.home : location.pathname === "/about" ? classes.about : "" }>
<Router>
<Switch>
<Route path="/" exact>
<Home />
</Route>
<Route path="/about">
<About />
</Route>
</Switch>
</Router>
</div>
)
}
export default App
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
.
You would need to either make style a state or secondly you can just do this directly

How To Translate React Router Function to Typescript?

I Start Work On React Project used react-router-dom and the client need to convert project code to Typescript
I Build 2 folder "RouteWrapper.js" and "ProviderRoutes.js"
1- "RouteWrapper.js"
import React from 'react';
import PropTypes from 'prop-types';
import { Route, Redirect } from 'react-router-dom';
export default function RouteWrapper({
component: Component,
isPrivate,
...rest
}) {
const signed = false;
if (!signed && isPrivate) {
return <Redirect exact to="/signin" />;
}
if (signed && !isPrivate) {
return <Redirect to="/" />;
}
return (
<Route {...rest} component={Component} />
);
}
RouteWrapper.propTypes = {
isPrivate: PropTypes.bool,
component: PropTypes.oneOfType([PropTypes.element, PropTypes.func])
.isRequired,
};
RouteWrapper.defaultProps = {
isPrivate: false,
};
2- "ProviderRoutes.js"
import React from 'react';
import { Switch } from 'react-router-dom';
// Components
import Route from './RouteWrapper';
import Authentication from '../Layouts/Authentication/Authentication.Layout';
import ChatApplication from '../Layouts/ChatApplication/ChatApplication.Layout';
export default function ProviderRoutes() {
return (
<Switch>
<Route exact path={["/signin", "/signup", "/reset-password"]} component={Authentication} />
<Route path="/" component={ChatApplication} isPrivate />
</Switch>
)
}
I believe the issue is mostly in RouteWrapper. First, let’s assume you’ll no longer want to use
prop types, since types are now checked at compile time by TypeScript.
These are the basics:
React is exported using module.exports = React. This means the technically correct way to import
React is import * as React from 'react';. Alternatively you can set "esModuleInterop": true in
tsconfig.json.
The return type of React components is React.ReactElement.
Also it’s ok to use destructuring to assign simple default props in functional components.
For <RouteWrapper /> specifically component is extracted from props, and then passed to
<Route /> along with the other props. This means it might as well be included in the rest props.
Since the rest props are passed to <Route />, the type of props for <RouteWrapper /> should
extend RouteProps from react-router-dom.
RouteWrapper would look like this:
import * as React from 'react';
import { Redirect, Route, RouteProps } from 'react-router-dom';
interface RouteWrapperProps extends RouteProps {
isPrivate: boolean;
}
export default function RouteWrapper({
isPrivate = false,
...rest
}: RouteWrapperProps): ReactElement {
const signed = false;
if (!signed && isPrivate) {
return <Redirect exact to="/signin" />;
}
if (signed && !isPrivate) {
return <Redirect to="/" />;
}
return <Route {...rest} />;
}
If you really want to use propTypes or defaultProps, type safety can be added using React.FC.
import * as PropTypes from 'prop-types';
import * as React from 'react';
import { Redirect, Route, RouteProps } from 'react-router-dom';
interface RouteWrapperProps extends RouteProps {
isPrivate: boolean;
}
const RouteWrapper: React.FC<RouteWrapperProps> = ({ isPrivate, ...rest }) => {
const signed = false;
if (!signed && isPrivate) {
return <Redirect exact to="/signin" />;
}
if (signed && !isPrivate) {
return <Redirect to="/" />;
}
return <Route {...rest} />;
};
RouteWrapper.propTypes = {
isPrivate: PropTypes.bool,
};
RouteWrapper.defaultProps = {
isPrivate: false,
};
export default RouteWrapper;
Beware the preferred way of writing routes using react-router is to use children, not the
component prop.
import * as React from 'react';
import { Switch } from 'react-router-dom';
// Components
import RouteWrapper from './RouteWrapper';
import Authentication from '../Layouts/Authentication/Authentication.Layout';
import ChatApplication from '../Layouts/ChatApplication/ChatApplication.Layout';
export default function ProviderRoutes(): React.ReactElement {
return (
<Switch>
<Route exact path={['/signin', '/signup', '/reset-password']}>
<Authentication />
</Route>
<Route isPrivate path="/">
<ChatApplication />
</Route>
</Switch>
);
}
This should help you get started converting the rest of the application. :)

reactjs router not rendering components

I have reactjs setup with routes but my routing is not working. When I load the page it works but when I click on the links the URL changes but the component does not render. I tried to put as much as I can in the sandbox. load with URL/admin and click on logout etc.
https://codesandbox.io/s/o5430k7p4z
index
import React, { Component } from 'react'
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore, applyMiddleware, combineReducers } from 'redux';
import { BrowserRouter, Route, browserHistory } from 'react-router-dom';
import promise from 'redux-promise';
import { createLogger } from 'redux-logger';
import App from './App'
import reducers from './reducers';
require("babel-core/register");
require("babel-polyfill");
import 'react-quill/dist/quill.snow.css'; // ES6
const logger = createLogger();
const initialState = {};
const createStoreWithMiddleware = applyMiddleware(promise)(createStore);
ReactDOM.render(
<Provider store={createStoreWithMiddleware(reducers)}>
<BrowserRouter>
<App/>
</BrowserRouter>
</Provider>
, document.getElementById('root'));
App
import React, { Component } from 'react'
import { Switch, Route } from 'react-router-dom';
import ReactGA from 'react-ga';
ReactGA.initialize('UA-101927425-1');
import { connect } from 'react-redux';
import { fetchActiveUser } from './actions/index';
import { bindActionCreators } from 'redux';
import {getHttpRequestJSON} from './components/HTTP.js'
import Header from './components/header';
import Logout from './components/logout';
import SideBar from './components/sidebar';
import HomeContent from './containers/home';
import Ldapuser from './components/ldapuser';
import Admin from './components/admin/admin';
function fireTracking() {
ReactGA.pageview(window.location.pathname + window.location.search);
}
class App extends Component {
constructor(props){
super(props);
this.state = {
isGuest : false,
isSupp : false,
loading: true,
version: '',
};
}
initData = () => {
let self = this;
getHttpRequestJSON('/api/user/get/user/method/is/guest/format/json?quiet=1')
.then((response) => {
let isGuest = response.body.recordset.record.isGuest;
if(isGuest){
/*$(".logo").trigger('click');
//$("#overlay").show();
$('#modalIntro').modal('toggle');
$("#modalIntro").on("hidden.bs.modal", function () {
$(".logo").trigger('click');
});*/
}
self.props.isGuest = isGuest;
self.props.loading = false;
//self.props.version = response.header.version;
self.setState({
loading : false,
version : response.header.version,
isGuest : isGuest
});
})
.catch(error => {
console.log("Failed!", error);
//$('#myModalError .modal-body').html(error);
//$('#myModalError').modal('show');
});
getHttpRequestJSON('/api/user/get/user/method/is/supp/format/json?quiet=1')
.then((response) => {
self.setState({
isSupp : response.body.recordset.record.isSupp
});
})
.catch(error => {
console.log("Failed!", error);
//$('#myModalError .modal-body').html(error);
//$('#myModalError').modal('show');
});
}
componentDidMount() {
this.props.fetchActiveUser();
this.initData();
}
render() {
return (
<div>
<Header activeUser={this.props.activeUser} loading={this.state.loading} version={this.state.version} title={`Home`} />
<SideBar />
<main>
<Switch>
<Route path='/index.html' render={()=><HomeContent activeUser={this.props.activeUser} isGuest={this.state.isGuest} isSupp={this.state.isSupp} />} />
<Route path='/home' render={()=><HomeContent activeUser={this.props.activeUser} isGuest={this.state.isGuest} isSupp={this.state.isSupp} />} />
<Route path='/logout' component={Logout}/>
<Route path='/ldapuser' component={Ldapuser}/>
<Route path='/admin' render={()=><Admin isGuest={this.state.isGuest} isSupp={this.state.isSupp}/>} />
</Switch>
</main>
</div>
);
}
}
//export default App;
function mapStateToProps(state) {
if(state.activeUser.id > 0){
ReactGA.set({ userId: state.activeUser.id });
}
// Whatever is returned will show up as props
// inside of the component
return {
activeUser: state.activeUser
};
}
// Anything returned from this function will end up as props
// on this container
function mapDispatchToProps(dispatch){
// Whenever getUser is called, the result should be passed
// to all our reducers
return bindActionCreators({ fetchActiveUser }, dispatch);
}
//Promote component to a container - it needs to know
//about this new dispatch method, fetchActiveUser. Make it available
//as a prop
export default connect(mapStateToProps, mapDispatchToProps)(App);
The codesandbox is not working, but I think what is happening to you is a very common problem when using react-redux and react-router. The connect HOC of react-redux has a builtin SCU (shouldComponentUpdate), so for it to know to rerender is requires to receive new props. This can be done using the withRouter hoc of react-router. Simply wrap connect(..)(MyComponent) with withRouter(connect(..)(MyComponent)) or do it clean and use compose (from recomponse for example);
const enhance = compose(
withRouter,
connect(mapStateToProps)
)
export default enhance(MyComponent)
Make sure not to do it the other way around, because that does not work.

React & Redux - state getting empty after route changed

I'm building a react & redux application and the problem I'm having is that after I do browserHistory.push('/myroute') and being successfully routed, I see that my state has been cleared, and while I need some data that's on the state from the previous route.. I still haven't found out if this is natural or not
My case is that I need to transfer data between routes.. I thought that is what state is for
this is my log:
action # 16:21:35.917 ON_ACTIVATE_FINISHED
counter.js:68 Object {counter: Object, registerReducer: Object, routing: Object}
core.js:97 action # 16:21:35.928 ##router/LOCATION_CHANGE
register.js:9 Object {}
core.js:97 action # 16:21:38.840 INPUT_PW_CHANGED
routes.js:
// #flow
import React from 'react';
import { Route, IndexRoute } from 'react-router';
import App from './containers/App';
import HomePage from './containers/HomePage';
import CounterPage from './containers/CounterPage';
import RegisterPage from './containers/RegisterPage';
export default (
<Route path="/" component={App}>
<IndexRoute component={CounterPage} />
<Route path="/counter" component={CounterPage} />
<Route path="/home" component={HomePage} />
<Route path="/register" component={RegisterPage} />
</Route>
);
CounterPage.js:
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Counter from '../components/Counter';
import * as CounterActions from '../actions/counter';
function mapStateToProps(state) {
return {
counter: state.counter,
key: state.key
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(CounterActions, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Counter);
RegisterPage.js:
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import Register from '../components/Register';
import * as RegisterActions from '../actions/register';
function mapStateToProps(state) {
return {
pw: state.pw
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(RegisterActions, dispatch);
}
export default connect(mapStateToProps, mapDispatchToProps)(Register);
reducers/counter.js:
import { Router, hashHistory } from 'react-router';
export const INPUT_KEY_CHANGED = 'INPUT_KEY_CHANGED';
export const ACTIVATE_KEY = 'ACTIVATE_KEY';
export const ON_ACTIVATE_FINISHED = 'ON_ACTIVATE_FINISHED';
export function onInputChanged(e) {
return {
type: INPUT_KEY_CHANGED,
data: e.target.value
};
}
export function activate() {
return {
type: ACTIVATE_KEY
};
}
export function onActivateFinished(json) {
return {
type: ON_ACTIVATE_FINISHED,
json
}
}
const SERVER_ADDRESS = 'http://*******:9001';
export const fetchActivationKey = () => (dispatch, getState) => {
var request = require('request-promise');
dispatch(activate())
const key = getState().counter.key;
return request(`${SERVER_ADDRESS}/invite/${key}`)
.then((fHost) => {
return request(`http://${fHost}:9000/api/start/${key}`)
})
.then(json => {
dispatch(onActivateFinished(json))
let currentState = getState();
if (currentState.counter.model.status === 0) {
hashHistory.push('/register');
}
});
}
Any ideas?
Based on https://github.com/reactjs/react-redux/blob/master/docs/api.md#provider-store and on my own app, it should look like this:
ReactDOM.render(
<Provider store={store}>
<Router history={history}>
<Route path="/" component={App}>
<Route path="foo" component={Foo}/>
<Route path="bar" component={Bar}/>
</Route>
</Router>
</Provider>,
document.getElementById('root')
)
But I don't see the Provider and the Router in your code, the Provider is here to pass the main state to all components and without it I'm not sure it would work properly.
Normally, you can’t use connect() without wrapping the root component in Provider.
Let's have a try at this.
Take this code
.then(json => {
dispatch(onActivateFinished(json))
let currentState = getState();
if (currentState.counter.model.status === 0) {
hashHistory.push('/register');
}
});
and change it to this:
.then(json => {
dispatch(onActivateFinished(json))
let currentState = getState();
this.setState({counter: currentState.counter});
if (currentState.counter.model.status === 0) {
hashHistory.push('/register');
}
});
I'm still learning React and by no means am any kind of expert. So I am not 100% certain this will work. But it is an effort to assist based off of what I currently know.

Categories