react js import component only if previous component is loaded - javascript

I have index.js file which is starting point of my react application. I am importing Login.js and Full.js file in index file. Here is my index.s file
import Login from './views/Login/Login';
import Full from './containers/Full/';
ReactDOM.render((<Provider store={store}>
<HashRouter>
<Switch>
<Route exact path="/" name="Login Page" component={Login}/>
<Route path="/login/:AUTHKEY" name="Login" component={Login}/>
<Route path="/" name="Home" component={Full}/>
</Switch>
</HashRouter>
</Provider>
),document.getElementById('root'));
In my Login.js page, i am receiving auth key in URL. e.g http://localhost:8080/#/login/123456
I am storing this authkey in localstorage.
I have one constant file which is imported in Full.js file, this constant file is common to all routing components. I am passing this localstorage authkey to Constant file. Then i use this authkey from Constant.js file in API calls.
Here is my Constant.js file (Imported in Full.js page)
let authkey = localStorage.getItem("AUTHKEY");
export default {
AXIOSCONFIG:{
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'authKey':authkey
}
}
}
The problem is importing of Login and Full is asynchronous so when Login page loads, Full.js component also loads and then Constant.js file shows authkey as null (because authkey in localStorage is not set yet). I am trying to achieve is import Full.js component only if authkey is set to localStorage (this happens in Login.js page)

You cannot delay importing. The solution is to load authkey at the right point in time, after the localStorage item has been set:
var authkey;
export default {
AXIOSCONFIG: {
init: function() {
authkey = localStorage.getItem("AUTHKEY");
},
headers: {
'Content-Type': 'application/json;charset=UTF-8',
'authKey': authkey
}
}
}
Elsewhere, run Constant.AXIOSCONFIG.init(); before making requests. You can also turn headers into a function that loads the authkey, then returns the headers.

you can add a condition to the render of Full component.
<Route path="/" name="Home" component={() => localStorage.getItem("AUTHKEY") ? <Full /> : null }/>

Related

How to avoid 404 page in react-router?

I'm working on a simple example using React Router.
I created it using create-react-app
On a local server, each link goes well
ex) localhost:3000/login, localhost:3000/ product, etc.
After deploying to my domain, I get a 404 error when I enter my link.
ex) myDomain.com/login, myDomain.com/product
It looks good on the local server, so I think there's no problem with the source code.
Then, I received an answer to redirect to the index.html page when the 404, 403 ... etc page appears
Are localhost:3000 and localhost:3000/index.html the same?
On the main page (localhost: 3000 or myDomain.com),
is well rendered.
In index.html (localhost: 3000 / index.html or myDomain.com/index.html)
it only renders up to h1 tag above {Home}. Is something wrong from here?
Please help me T.T
App.js
class App extends Component{
render(){
return (
<div className="App">
<Header/>
<h1>asd</h1>
<h1>asd</h1>
<Route exact path = "/" component = {Home}/>
<Route path = "/about" component = {About}/>
<Route path = "/event" component = {Event}/>
<Route path = "/qna" component = {QnA}/>
<Route path = "/login" component = {Login}/>
<Route path = "/join" component = {Join}/>
<Route path = "/product" component = {Product}/>
</div>
);
}
}
export default App;
Root.js
const Root = () => {
return (
<BrowserRouter>
<App/>
</BrowserRouter>
);
};
export default Root;
You can wrap your route components in a switch component and render a default component if none match like below.
<Switch>
<Route exact path = "/" component = {Home}/>
<Route path = "/about" component = {About}/>
<Route path = "/event" component = {Event}/>
<Route path = "/qna" component = {QnA}/>
<Route path = "/login" component = {Login}/>
<Route path = "/join" component = {Join}/>
<Route path = "/product" component = {Product}/>
<Route component={NoMatch} />
</Switch>
Obviously you'd change the NoMatch component with whatever you'd want your default component to be.
You should add the basename to the BrowserRouter component in the root
ReactDOM.render(
<BrowserRouter basename='/My-App/'>
<React.StrictMode>
<App />
</React.StrictMode>
</BrowserRouter>
,
document.getElementById('root')
);
Also, you should make sure in 404 cases you are redirected to index.html because it's a SPA and everything is happening there, you do this by simply replacing this line with "build" script in package.json
"build": "react-scripts build && cp build/index.html build/404.html",
I don't think this is your react app issue, rather it's how your app is deployed.
I hope you have deployed your app using production build (using npm run build).
If so, this is most likely that your web server is not redirecting to the right entry.
You need to tell your web server(nginx or caddy whatever you are using) to point to /index.html when hitting 404. Here is a simple config for nginx.
https://www.barrydobson.com/post/react-router-nginx/

Creating dynamic Link with some text before it

I was building a search engine for custom project.
There I have a search bar from where user can search.
When the user searches, I want the given link to work as it works in case of google
www.google.com/ search? queryRelatedInfo
Notice the search? and then whatever query/parameter/ID
for this I tried something like this in
import React, {Component} from 'react';
import {
BrowserRouter,
Route,
Switch,
Redirect,
} from 'react-router-dom';
import SearchScreen from "./container/searchScreen.js"
import HomeScreen from "./container/home.js";
class route extends Component {
render () {
return (
<BrowserRouter>
<div>
<Switch>
<Route path ="/" exact render ={(props) => <HomeScreen {...props}/>} />
<Route path ="/search?:id" exact render ={(props) => <SearchScreen {...props}/>} />
</Switch>
</div>
</BrowserRouter>
)
}
}
export default route
Notice, <Route path ="/search?:id" above.
Unfortunately this didn't worked out.
I understand that <Route path ="/:id" works but how can i make <Route path ="/search?:id to work i.e how can I make some link like http://localhost:3000/search?9e9e to work
I think this is related with historyApiFallback. That parameter;
(https://webpack.js.org/configuration/dev-server/#devserver-historyapifallback)
When using the HTML5 History API, the index.html page will likely have to be served in place of any 404 responses. devServer.historyApiFallback is disabled by default. Enable it by passing:
module.exports = {
//...
devServer: {
historyApiFallback: true
}
};
Your react app is a single page application. So all path except home path actually is an virtual path, they are not physically exist. The paths must routed to home path. So react-router can manage.
you don't need to put the path like this /search?:id, just put it search
<Route path ="/search" exact render ={(props) => <SearchScreen {...props}/>} />
then inside your SearchScreen component, get the value of search parameter from the URL, check this issue will help.
after the user make search, pass the value like this /search?s=value_here

Get React router to cause a re-render

I have mixed content on my homepage. The user specific content is an edit button next to their own content.
When the user logs out via a logout route this code gets executed:
import React from 'react'; // needed
import ReactDOM from 'react-dom';
import Home from './components/layout/Home.js';
import Login from './Login/Login';
import PollDetails from './components/layout/PollDetails.js';
import EditPoll from './components/presentation/EditPoll.js';
import CreatePoll from './components/presentation/CreatePoll';
import Container from './components/containers/Container.js';
import {Route,Router,browserHistory,IndexRoute} from 'react-router';
import Auth from './utils/Auth';
const mountNode = document.getElementById('root');
ReactDOM.render(
<Router history={browserHistory}>
<Route path="/" component={Container} >
<IndexRoute component={Home} />
<Route path="login" component={Login} />
<Route path="logout" onEnter={(nextState, replace) => {
Auth.deauthenticateUser();
console.log('Logging out src/app.js');
Auth.clearCookie();
// change the current URL to /
replace('/');}} />
<Route path="Polldetailfull/:id" component={PollDetails} />
<Route path="Editthepoll/:id" component={EditPoll} />
<Route path="createPoll" getComponent={(location, callback) => {
if (Auth.isUserAuthenticated()) {
callback(null, CreatePoll);
} else {
callback(null, Home);
}
}} />
</Route>
</Router>,mountNode);
However, the replace('/'); sends you back to the home page but doesn’t re-render any components. Note there is no state to change here. Do I need a state to force the re-render?
Note, if you press refresh on the browser the desired behaviour happens. I tried looking on React Router's code but could not find much about events. To be honest, I don't fully understand onEnter={(nextState, replace) =>
You could use location.reload() to cause it to re-render
onEnter -> this function use when component going to render on browser.
For your idea, You need to use route the component based log details in component life cycle of particular components.below code to be use in path component life cycle(componentWillMount or componentDidMount) and route the page as want .
browserHistory.push('/location-path-name');
call the component based log details in router like below sample
<Route path="createPoll" component={Auth.isUserAuthenticated() ? CreatePoll : Home}/>

ReactJs cannot acess nested route

I have an issue using nested routes with react-router.
Here is my code (two simple react components, routes file to access comp1/comp2) :
House.js
export default connect(st => st)(class House extends React.Component {
render() {
return (
<div>
{this.props.children}
</div>
);
}
})
Window.js
export default connect(st => st)(class Window extends React.Component {
render() {
return (
<div >
hey hey
</div>
);
}
})
routes.js
export const routes = (
<Router history={ history }>
<Route path="/house" component={House}>
<Route path="/house/window" component={Window} />
</Route>
</Router>
);
When I redirect to "/house/window" programmatically, I can access the route and the page shows "hey hey".
If I want to access the url directly :
localhost:8080/house/window
It shows a blank page and a console error :
Request URL:http://localhost:8080/house/window
Request Method:GET
Status Code:304 Not Modified
And then :
GET http:// localhost:8080 /house/js/bundle.js (404)
Also, http:// localhost:8080 /house/ (with trailing slash) shows the same error.
I really don't understand this weird redirection http:// localhost:8080 /house/js/bundle.js
I'm probably doing something wrong, but after crawling stackoverflow, I still can't see it.
I found the issue : my bundle.js script included in index.html was included with a relative path 'js/bundle.js' so I changed it for '/js/bundle.js'.
Sadly, it didn't make any problem until I wanted to nest some routes.
Nested routes cannot have parent path included in path attribute:
export const routes = (
<Router history={ history }>
<Route path="/house/" component={House}>
<Route path="window" component={Window} />
</Route>
</Router>
);

react-router 2.0 doesn't route

I have this simple code that doesn't work. I took it from the react-router project page and modified slightly for it to look a bit better.
Setup
I have several very simple react components:
var IndexPage = React.createClass({
render(){
return (<h1>Index Page</h1>);
}
});
var AboutPage = React.createClass({
render(){
return (<h1>About page</h1>);
}
});
var NotFoundPage = React.createClass({
render(){
return (<h1>Not found page</h1>);
}
});
Also I have made a setup of react router:
var ReactRouter = require('react-router');
var Router = ReactRouter.Router;
var Route = ReactRouter.Route;
var BrowserHistory = ReactRouter.browserHistory;
var Render = ReactDOM.render;
And that's how I use react router 2.0.
Render((
<Router history={BrowserHistory}>
<Route path="/" component={IndexPage}>
<Route path="about" component={AboutPage}/>
<Route path="*" component={NotFoundPage}/>
</Route>
</Router>
), document.body)
I use BrowserHistory (not HashHistory) to avoid hash in urls.
My server is raised under IIS 10 (Windows 10) on 8080 port.
Problem
http://localhost:8080/
goes to IndexPage component. This is correct.
http://localhost:8080/about
goes to IIS 404 error page. Routing doesn't work in this case
http://localhost:8080/ttt
goes to IIS 404 error page again.
So the router doesn't see this nested paths that go after /. And it doesn't even care about whether they are correct or not.
What can cause such a strange behavior?
Thanks in advance!
Update
I've found out that the next string solves the problem with a client routing:
{this.props.children}
This is the fixed code:
var IndexPage = React.createClass({
render(){
console.log('index page render');
return (<div>
<h1>Index Page</h1>
<Link to={ '/about' }>about</Link>
{this.props.children}
</div>);
}
});
Is your server configured to map all application-paths to your index.html? You should never get a IIS 404 if your server would map all path to your index file, as it always would deliver this one.
React-router is a client-side routing solution(also works in server side, but it seems you are using .Net as the server side handler).
You can try this(Link from React-Router):
<Link to={ pathname: 'about' }>
about
</Link>
Put it in the index page's component, and click the link, the react-router will work.
Update:
{this.props.children} ref to the inner component(AboutPage, NotFoundPage).
If you change code to that:
<Route path="/" component={IndexPage} />
<Route path="/about" component={AboutPage}/>
<Route path="*" component={NotFoundPage}/>
It will works.(remove the {this.props.children} in IndexPage if there is no nesting routes).
I was able to solve my issue linking directly to URLs by adding --history-api-fallback to my webpack-dev-server command.
Setting this flag prompts webpack-dev-server to serve the index page instead of 404. The index page will then route correctly on the client side.

Categories