ReactJS route shows empty page - javascript

Using ReactJS frontend, with react-router, I somehow get an empty page when being redirected to a new route.
In a component I use the following to achieve a redirect:
if (this.props.showUnknownErrorPage) {
return <Redirect push to={`/${this.props.locale}/unforeseenerror/`}/>
}
This does lead to the correct URL:
http://127.0.0.1:8000/en/unforeseenerror/
But the page that shows is totally empty, just a blank page.
The route that should get the component to show:
<Route path={`${this.props.match.path}/unforeseenerror/`}
render={(props) => <UnknownErrorPage {...props}
setGreeneryAppState={this.setGreeneryAppState}/>}
/>
I have similar routes that look quite the same, and they work without problem. Can anyone help me debug this?
What I have already tried:
Changed component content, to just an H1 element (no difference)
Changed to different route: a one line route like this:
<Route path={${this.props.match.path}/about} component={AboutPage}/>
Tried a hardcoded route path /en/unforeseenerror/
`

Related

How to pass and intercept data with Link in react-router-dom v5 [duplicate]

This question already has answers here:
How to pass data from a page to another page using react router
(5 answers)
Closed last month.
I am making a simple chat-app. Users submit a form with name and room, and are sent to the room, with the username. The problem is, I cannot figure out how to pass the username through via the Link. This is the relevant code:
<Link to={{ pathname: `/${room}`, state: { the: user } }}>
Enter room
</Link>
I use simple useState hooks to set room and username from input. From what I have read, this way of doing it is deprecated, and I cannot find a proper answer for react-router-dom#5, only 4 and below.
Also, I have no idea how I am supposed to intercept this data. This is my App.js code:
return (
<Router>
<div className='app' >
<Switch>
<Route exact path='/'>
<Menu />
</Route>
<Route exact path='/:room'>
<ChatApp />
</Route>
</Switch>
</div>
</Router>
);
So as you can see, the link sends you to the ChatApp component. To make it as simple as possible, the top of that looks like this:
const ChatApp = (props) => {
but when I console.log(props), all I get is an empty array. Does anyone know a reliable way of passing and intercepting data via links? Perhaps it should be done a different way?
Not necessarily the right answer, but the way things look, in rrd#5, you cannot, and you are forced to send the props as params. Not sure for objects though

Issue with routing in React when user directly hits url that requires id from another component

I have this issue that I am facing in react related to routing.
There is this button which appears on the screen which appears only if the user is authenticated and thus it's a private route "/home/coupons".
When user clicks on any of the coupons ,I directed the user to
http://localhost:3000/coupons?id=6
Using this props.history:
this.props.history.push({
pathname: '/coupons',
search: '?id='+id,
})
I did the routing for this in my App.js:
<Route path="/coupons" component={CouponsRedeem}/>
The Component CouponsRedeem needs the id from the Component where users gets directed when he hits /home/coupons.
My concern is that if user directly hits the route /coupons without navigating to /home/coupons,the entire web app break since we don't get any get anything in this.props.location.
How do I make sure that such things don't happen?
Is my routing done correctly?
Any suggestions are most welcomed.
If it lacks information ,I will add more code snippets.
I am using react-router.
The solution to your problem is pretty simply. Either you have a default value that you use when the user didn't navigate from home/coupons to coupons since history.location.search doesn't have anything or you reconfigure your Route to use Router param where in instead of query your specify your Route like
<Route
exact
path="/coupons/:id"
component={Coupon.Show}
/>
and use it like
this.props.history.push({
pathname: `/coupons/${id}`,
})
or else if the coupon isn't received you can redirect the user to the home/coupons route
Looking at your implementation, I would assume that you're using either react-router or reach-router ?
If so, in my experience I tend to use route props to specify that an ID should be expected.
I would usually setup a route for the index and a route for showing an object and a default route for no matches (think of that like a 404) like so:
<Route
exact
path="/coupons"
component={Coupon.Index}
/>
<Route
exact
path="/coupons/:id"
component={Coupon.Show}
/>
<Route component={NoMatch} />
Specifying the "exact" prop ensures that it'll only render that component when the path matches correctly, so if you dont want an index route, you could omit it completely and when you navigate to that it'll fall back to the NoMatch component
The example I provided would change how it looks in the address bar for a more RESTful looking approach so instead of
http://localhost:3000/coupons?id=6 it would be http://localhost:3000/coupons/6
In the show component you can then access the prop value by the name that you specify after the colon ":id" in your Show component, using the props provided by the router like so:
let { id } = this.props.match.params;
I hope this helps

POST request from react child component in express

I am using the MERN stack (With react-router and redux) for my program.
In my application, I have a <Navbar /> component as well as a <SearchBar> component.
I used create-react-app to handle the react side of things, and as i'm sure you all know, everything is ultimately contained within App.js
Within App.js, Navbar is outside of the react router switch statement like so.
<Provider store={store}>
<Router>
<div>
<NavBarContainer />
<Switch>
<Route exact path="/" component={Homepage} />
<Route exact path="/ProfilePage" component={ProfilePageContainer} />
<Route exact path="/SearchPage" component={SearchPageContainer} />
<Route exact path="/LoginPage" component={LoginContainer} />
</Switch>
</div>
</Router>
</Provider>
My problem is that SearchBar is a child component of Navbar like so.
class Navbar extends Component {
render(){
return (
***navbar stuff
{this.props.loggedIn && <SearchBar />}
***navbar stuff
)
}
}
And when I try to make a POST request from <SearchBar /> like this:
addSearch = (event) => {
if(this.props.loggedIn){
fetch('/api/SearchPage', {
headers : {
"Accept" : "application/json",
"Content-Type" : "application/json"
},
method : 'POST',
body : JSON.stringify({
username : this.props.username,
search : this.search.value
}).then(function(value){
return value.json()})
.then(function(data){
console.log("SearchData", data)
}).bind(this)
})
}
}
Where addSearch() is called within the SearchBar with onClick(this.addSearch).
When I do this, the POST request comes from whatever page is rendered under my Navbar!
My page says:
Cannot POST /api/[Pagename}.js
Whatever page is currently rendered under Navbar with react switch will replace [Pagename]
How can I make <SearchBar /> create a POST request within itself?
Or, if that is not possible, how can I contain that post request within the <Navbar> component?
Something I'm considering, is that it has something to do with the fact hat I'm using a body parser, and the current body of the page happens to be whatever page is loaded. However, I seem to define the body: within the POST request so this doesn't make much sense.
For now, i'm simply going to put all of the code and logic of the <SearchBar> component within the <Navbar> and the search page, but I suspect that there is a much better way to do this (while leaving <SearchBar> within its own component).
Ideally, I'd like to send a POST request just from <SearchBar>.
I know I'm probably missing something common here.
Here is the endpoint in the express file (It is just set up for testing)
```
app.post('/api/SearchPage', function(req, res done){
if(err) done(err);
done(null, res.json({"Test" : "testobj"}))
}'
```
From the given code, it seems like its the url in fetch() that is the issue here. Since you are only stating '/app/SearchPage', then it is assumed to be part of the React app (which it is not, since its should hit your API endpoint).
You should try to insert the url for the endpoint. Is is sometimes running on a different port than the React application (depending on your setup). Endpoint could be something like http://localhost:3050/api/SearchPage, which should be set in the URL parameter of your fetch() method.
I took a break today but the answer seems obvious at the moment.
When I do fetch(), all react does is append the URL (in this case /API/Page) to localhost/[pageimon]
Because all of my routing is handled client side by react router, my URL is whatever page I'm on. (I did not do any routing with express).
Since the navbar is out side of all switching (on purpose), whatever is contained in there will not make a successful post request, as all fetch calls will simply read the URL.
So I have to figure out a way to either bypass this (possibly a fetch parameter, or a react middleware module).

React router: component not updating on url search param change

I have a React application that uses URL search params. Depending on the value of the search parameter v, the component is supposed to show different content.
A possible URL might look like this:
http://localhost:3000/hello?v=12345
Once the v query parameter changes in the URL, I would like my component to update.
http://localhost:3000/hello?v=6789
I'm using using react-router in my App component to display the different components depending on the route. The App component is wrapped into a BrowserRouter component.
render() {
return (
<Switch>
<Route path="/hello" component={Hello}></Route>
<Route path="/" component={Home}></Route>
</Switch>
);
}
If a user clicks on something and the URL search param v changes, I would like the component to display different content. Currently, the URL search param does change, but the component doesn't render again. Any ideas?
As #forJ correctly pointed out, the main idea is to make the component re render once the URL parameters change. I achieved it like so:
render() {
return (
<Switch>
<Route path="/hello" render={() => (<Hello key={this.props.location.key}/>)}></Route>
<Route path="/" component={Home}></Route>
</Switch>
);
}
this.props.location.key changes every time the URL changes (also if the query params change). So if you pass it as props to the component, then the component re renders on URL param changes, even though the base URL (the URL without the URL params) hasn't changed.
I also had to use the withRouter higher order component to make it work.
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Hello));
You have not provided enough information so I cannot be 100% sure where you are going wrong but I can see 1 problem right now in your code. First, you have to let the router know that you will be using parameters. So for example below code
render() {
return (
<Switch>
<Route path="/hello/:yourParam" component={Hello}></Route> // you need the colon here
<Route path="/" component={Home}></Route>
</Switch>
);
}
The above will tell the route that parameter called yourParam will be accessible from the URL
Then it has to be accessed in your component and put into render function somehow (use it to retrieve data from database to render data, just render params directly, etc).
For example below
render(){
<div>
{this.props.match.params.yourParam}
</div>
}
This way, your component will re-render everytime there is param change.
EDIT
Since you want to use query instead of parameter, you would have to retrieve it by going. this.props.match.query.v. You would still have to make sure that variable is rendered depending on query change
If you use useEffect hook make sure to have [props.match.params] instead of empty array []
useEffect(() => {
(async () => {
// Fetch your data
})();
}, [props.match.params]) // <-- By this it will get called when URL changes
of course for class components this.props.match.params

In React, How do I redirect a user back to the index with altered state

In my React.JS application, I want to create a link which does nothing more than alter the client's state, but show the main index page. For example, the main page is:
http://example.com/#/
This shows the main index page. Now, if a user is directed to this page:
http://example.com/#/check?arg=abcd
I would want to still show the user the main index page, but have the this.props variable be affected by the arg=abcd
I define my routes with:
var routes = (
<Route handler={APP}>
<DefaultRoute handler={Index} />
<Route name="check" path="check" handler={check}></Route>
</Route>
);
So I do have a route which takes in a check path, but again my goal is to just use the argument to check and still keep showing the regular index page.
What is the most efficient way of doing this with React.JS?
I just realized that I could circumvent the need of a second page and router. All I need to do is use an argument handler on the index page. I am away from work and on mobile so I will answer my own question tomorrow when I get in.
Update --
So this is how I got it working:
I added a new line to the route set up:
var routes = (
<Route handler={APP}>
<DefaultRoute handler={Index} />
<Route path="/arg1/:arg1" handler={Index} />
</Route>
);
The line with arg1. Then I made sure the handler to that path was {Index}. Now, within my component, I have the following line:
componentWillMount() {
this._handleArgs(this.props.params.arg1);
},
Which will handle (or not-handle if arg1 is null) any args before mounting the component.
So, no need to add a new component, just another route to the same component and some helper functions.

Categories

Resources