I am working on a React JS project, inside the project I am using React Router v4 to create a client-side route.
This is the project live URL: https://gokhana.herokuapp.com/
On the homepage, a customer will search for the city/location (Indian cities only), whenever customer will select the location (https://prnt.sc/jsy8rp), I want to load the next route i.e https://gokhana.herokuapp.com/restaurants.
I am using <Redirect />
for redirecting the page to /restaurants
route.
When the /restaurants
route is loaded, the page is not loading properly, everything is messed. Check this how it is loading https://prnt.sc/jsy96i
Now, if I reload the same URL, the page is loaded correctly without any problem https://prnt.sc/jsya4t
Redirecting to the route with <Redirect />
creates a problem, while reloading the same route works fine.
I have checked for CSS and JS files all of them are loading properly.
I am unable to figure out this issue.
app.js file
import React from 'react';
import ReactDOM from 'react-dom';
import {Provider} from 'react-redux';
import store from './store';
import $ from 'jquery';
import 'bootstrap/dist/css/bootstrap.min.css';
import Routers from './routes/AppRouter';
//Import CSS files
import './styles/google-font.css';
import './styles/base.css';
ReactDOM.render(
<Provider store={store}>
<Routers />
</Provider>,
document.getElementById('root')
);
index.html file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>GoKhana</title>
<link rel="icon" type="image/png" href="./images/favicon.png">
<link rel="stylesheet" type="text/css" href="./dist/styles.css">
</head>
<body>
<div id="root"></div>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCmnIFpWp5ofkwDLZgCDLBat1VPEjOj_jA&libraries=places"></script>
<script src="./dist/bundle.js"></script>
<script src="./js/common_scripts_min.js"></script>
<script src="./js/functions.js"></script>
<script src="./js/modernizr.js"></script>
<script src="./js/cat_nav_mobile.js"></script>
<script>$('#cat_nav').mobileMenu();</script>
<script src="./js/ion.rangeSlider.js"></script>
<script src="./js/cat_nav_mobile.js"></script>
<script src="./js/theia-sticky-sidebar.js"></script>
<script src="./js/bootstrap3-wysihtml5.min.js"></script>
<script src="./js/dropzone.min.js"></script>
<script src="./js/tabs.js"></script>
<script src="./js/custom.js"></script>
</body>
</html>
AppRouter.js file
import React from 'react';
import {BrowserRouter, Route, Switch} from 'react-router-dom';
import HomePage from './../components/HomePage';
import AboutUs from './../components/AboutUs';
import ContactUs from './../components/ContactUs';
import PageNotFound from './../components/PageNotFound';
import RestaurantList from '../components/RestaurantList';
import RestaurantMenu from '../components/RestaurantMenu';
import UserDetails from '../components/UserDetails';
import OrderConfirmation from '../components/OrderConfirmation';
import CustomerAccount from '../components/CustomerAccount';
export default () => {
return (
<BrowserRouter>
<Switch>
<Route path="/" component={HomePage} exact={true}/>
<Route path="/about" component={AboutUs} />
<Route path="/contact" component={ContactUs} />
<Route path="/restaurants" component={RestaurantList} />
<Route path="/select-menu" component={RestaurantMenu} />
<Route path="/user-details" component={UserDetails} />
<Route path="/order-confirmation" component={OrderConfirmation} />
<Route path="/my-account" component={CustomerAccount} />
<Route component={PageNotFound} />
</Switch>
</BrowserRouter>
);
}
RestaurantList.js - This component is messed
import React from 'react';
import Header from './sections/Header';
import Footer from './sections/Footer';
import ImageSubHeader from './sections/ImageSubHeader';
import Filters from './sections/Filters';
import DisplayRestaurants from './sections/DisplayRestaurants';
export default () => {
return (
<div>
<Header />
<ImageSubHeader title="Search your Favorite Restaurant" showSearch = "true" />
<div className="container margin_60_35">
<div className="row">
<Filters />
<DisplayRestaurants />
</div>
</div>
<Footer />
</div>
);
}
ImageSubHeader.js
import React from 'react';
import subHeaderImg from './../../images/web-images/mainbanner.jpg';
export default (props) => {
return (
<section className="parallax-window" id="short" data-parallax="scroll" data-image-src={subHeaderImg} data-natural-width="1400" data-natural-height="350">
<div id="subheader">
<div id="sub_content">
<h1>{props.title}</h1>
<p>{props.subTitle}</p>
{props.showSearch &&
(<form method="post" action="list_page.html">
<div id="custom-search-input">
<div className="input-group ">
<input type="text" className=" search-query" placeholder="Your Address or postal code" />
<span className="input-group-btn">
<input type="submit" className="btn_search" value="submit" />
</span>
</div>
</div>
</form>)
}
{props.showOrder &&
(
<div className="bs-wizard">
<div className={(props.orderId >=1) ? "col-xs-4 bs-wizard-step complete" : "col-xs-4 bs-wizard-step disabled"}>
<div className="text-center bs-wizard-stepnum"><strong>1.</strong> Your details</div>
<div className="progress"><div className="progress-bar"></div></div>
<a href="#0" className="bs-wizard-dot"></a>
</div>
<div className={(props.orderId >=2) ? "col-xs-4 bs-wizard-step complete" : "col-xs-4 bs-wizard-step disabled"}>
<div className="text-center bs-wizard-stepnum"><strong>2.</strong> Payment</div>
<div className="progress"><div className="progress-bar"></div></div>
<a href="cart_2.html" className="bs-wizard-dot"></a>
</div>
<div className={(props.orderId >=3) ? "col-xs-4 bs-wizard-step complete" : "col-xs-4 bs-wizard-step disabled"}>
<div className="text-center bs-wizard-stepnum"><strong>3.</strong> Finish!</div>
<div className="progress"><div className="progress-bar"></div></div>
<a href="cart_3.html" className="bs-wizard-dot"></a>
</div>
</div>
)
}
</div>
</div>
</section>
);
}
Filters.js
import React from 'react';
export default () => {
return (
<div className="col-md-3">
<div id="filters_col">
<a
data-toggle="collapse"
href="#collapseFilters"
aria-expanded="false"
aria-controls="collapseFilters"
id="filters_col_bt
">
Filters
<i className="icon-plus-1 pull-right"></i>
</a>
<div className="collapse" id="collapseFilters">
<div className="filter_type">
<h6>Distance</h6>
<input type="text" id="range" value="" name="range" />
<h6>Type</h6>
<ul>
<li><label><input type="checkbox" checked className="icheck" />All <small>(49)</small></label></li>
<li><label><input type="checkbox" className="icheck" />American <small>(12)</small></label><i className="color_1"></i></li>
<li><label><input type="checkbox" className="icheck" />Chinese <small>(5)</small></label><i className="color_2"></i></li>
<li><label><input type="checkbox" className="icheck" />Hamburger <small>(7)</small></label><i className="color_3"></i></li>
<li><label><input type="checkbox" className="icheck" />Fish <small>(1)</small></label><i className="color_4"></i></li>
<li><label><input type="checkbox" className="icheck" />Mexican <small>(49)</small></label><i className="color_5"></i></li>
<li><label><input type="checkbox" className="icheck" />Pizza <small>(22)</small></label><i className="color_6"></i></li>
<li><label><input type="checkbox" className="icheck" />Sushi <small>(43)</small></label><i className="color_7"></i></li>
</ul>
</div>
<div className="filter_type">
<h6>Rating</h6>
<ul>
<li><label><input type="checkbox" className="icheck" /><span className="rating">
<i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star voted"></i>
</span></label></li>
<li><label><input type="checkbox" className="icheck" /><span className="rating">
<i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star"></i>
</span></label></li>
<li><label><input type="checkbox" className="icheck" /><span className="rating">
<i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star"></i><i className="icon_star"></i>
</span></label></li>
<li><label><input type="checkbox" className="icheck" /><span className="rating">
<i className="icon_star voted"></i><i className="icon_star voted"></i><i className="icon_star"></i><i className="icon_star"></i><i className="icon_star"></i>
</span></label></li>
<li><label><input type="checkbox" className="icheck" /><span className="rating">
<i className="icon_star voted"></i><i className="icon_star"></i><i className="icon_star"></i><i className="icon_star"></i><i className="icon_star"></i>
</span></label></li>
</ul>
</div>
<div className="filter_type">
<h6>Options</h6>
<ul className="nomargin">
<li><label><input type="checkbox" className="icheck" />Delivery</label></li>
<li><label><input type="checkbox" className="icheck" />Take Away</label></li>
<li><label><input type="checkbox" className="icheck" />Distance 10Km</label></li>
<li><label><input type="checkbox" className="icheck" />Distance 5Km</label></li>
</ul>
</div>
</div>
</div>
</div>
);
}
DisplayRestaurants.js
import React from 'react';
import GridListRestaurant from './GridListRestaurant';
export default () => {
return (
<div className="col-md-9">
<div id="tools">
<div className="row">
<div className="col-md-3 col-sm-3 col-xs-6">
<div className="styled-select">
<select name="sort_rating" id="sort_rating">
<option value="" selected>Sort by ranking</option>
<option value="lower">Lowest ranking</option>
<option value="higher">Highest ranking</option>
</select>
</div>
</div>
</div>
</div>
<GridListRestaurant />
<GridListRestaurant />
</div>
);
}
REDIRECT LOGIC SearchLocationBar.js
import React from 'react';
import {connect} from 'react-redux';
import {Redirect} from 'react-router-dom';
import {setLocation} from './../../actions/locationActions';
import {toggleLoader} from './../../actions/loaderActions';
class SearchLocationBar extends React.Component {
location = {}
state = {
redirect : false
}
componentDidMount() {
let autocomplete = document.getElementById('autocomplete');
let GoogleMapsApi = new google.maps.places.Autocomplete((autocomplete), {
types: '(regions)',
componentRestrictions: {country: 'in'}
});
google.maps.event.addListener(GoogleMapsApi, 'place_changed', () => {
this.location = {};
const place = GoogleMapsApi.getPlace();
this.location.latitude = place.geometry.location.lat();
this.location.longitude = place.geometry.location.lng();
place.address_components.forEach((address) => {
if(address.types.includes('locality')) {
this.location.city = address.long_name;
} else if(address.types.includes('administrative_area_level_2')) {
this.location.city = address.long_name;
} else if(address.types.includes('administrative_area_level_1')) {
this.location.state = address.long_name;
}
});
this.props.setLocation(this.location);
localStorage.setItem('location',JSON.stringify(this.location));
this.setState({redirect: true});
});
}
render() {
return (
<form autoComplete="off" method="post">
<div id="custom-search-input">
<div className="input-group ">
<input
type="text"
className=" search-query"
placeholder="Your Address or postal code"
id="autocomplete"
/>
{this.state.redirect ? <Redirect to='/restaurants' /> : ''}
<span className="input-group-btn">
<input type="submit" className="btn_search" value="submit" />
</span>
</div>
</div>
</form>
);
}
}
const mapStateToProps = (state) => {
return state;
};
const mapDispatchToProps = {
setLocation,
toggleLoader
};
export default connect(mapStateToProps, mapDispatchToProps)(SearchLocationBar);
After a lot of studies, I found the answer to my problem.
In React Router, if we redirect to the new route then JS libraries are not loaded. In my case, I was using the plugins which were injecting the HTML elements after the page load is complete.
Now, react routing will not load the page as everything here is virtual DOM, so the solution here was to load the JS libraries after routing is done.
So I used loadjs package.
1) Install
2) Import
3) Call it in componentDidMount() of the React Component
and this will resolve the problem.