What's the preferred way of doing POST/GET using react-router? - reactjs

I have a simple route in React:
<Route path="/listUsers" exact component={UsersList} />
Different component (navigation) holds the link to the UsersList:
<Link to="/listUsers">All users</Link>
My back-end is very simple, once you make get request to /listUsers it responds with all the users, like:
app.get('/listUsers', function (req, res) {
UserModel.find({}, function(err, users) {
res.send(users);
})
})
I'm facing two problems here:
when do I actually make the request? should I perform react's fetch on componentDidMount in UsersList component? or maybe on componentWillMount? so it will work like this - user clicks a link - I'm mounting component via react-router and at the same time - before/after mount performing fetch, does it make sense? I guess after fetching I should update the components internals somehow (possibly using props?),
my node server is at localhost:3000, so I should be hitting localhost:3000/listUsers, yet my React app is being served by Apache at localhost, so the <Link to="/listUsers"> actually points to a wrong URL, I guess I'll be able to provide the proper URL within React's fetch?
I know these are noobish questions but I'm sorry to say I found it very hard to make these clear to me and I'm not sure if https://facebook.github.io/react/docs/hello-world.html is the official React's documentation, because it's simply awful and it's next to impossible to find anything there.
Thank you so much.

Related

Apollo caching with React redirect doesn't get new items

I am using Apollo Client.
There's a route /restaurants/${restaurant_name}/places where it lists all the places for concrete restaurant_name.
Let's say I am on the /restaurans/france_res/places route. On that route, I can add new place for it. I add it and when it's done, I redirect users with history.push to the following route - /restaurans/france_res/places/place_name.
Now, if user goes to /restaurans/france_res/places route again (with no refresh, just react router's navigation), Apollo doesn't query the server any more and the places that route shows doesn't include the new one. This is because of the cache policy and it seems like the route /restaurans/france_res/places is already cached...
What could be the workaround for the following situation ?
using no-cache policy seems too harsh... Then what's the point of Apollo's caching policies in the first place ?
I don't use Redux, but I don't know how that could help me. There's a way with Redux, but it's not good.
Maybe, when new place gets added, I make user redirect to the route without history.push which will cause the hard refresh, causing queries to get executed again.
How do you handle situation like this ?

React Router V5 | setup 404 page | status from API

I am building a React JS app with react-router v5.
I have already set up a 404 page and it works well.
As you can see, in the console I’m getting response code I just need to understand how to set a 404 header in the React component from this api response.
I looked up this question and everyone says you should set it from server response, but I did not figure it out, because I'm here now for your help.
Thank you
import React from "react";
const baseURL = "https://dog.ceo/api/breeds/image/";
const phpRoute = "giveme404"; //if you put here "random" will work
class NotFoundPage extends React.Component {
componentDidMount() {
fetch(baseURL + phpRoute)
.then(response => response.json())
.then(function(response) {
console.log(response);
});
}
render() {
return <div>404 Error, Page not found</div>;
}
}
export default NotFoundPage;
codesandbox link
Response From Server
Get response from server to React
Here's an example error handling strategy you can adopt on the frontend.
Some highlights:
I added some sample React routing with 404 page to which to redirect
when certain conditions occur.
I used the axios library, because I'm not sure if the built-in fetch
method in JS offers the same control as axios in terms of global
error handling. Logic for api access logic is in api.js file, there
you can see I added an error interceptor (more about interceptors here) which kicks off whenever
there's an unhandled http error and redirects to the not found page
only in case of 404 status code.
The trickies part is the history object. As you may know, React
router keeps internally its own history object which handles route change subscriptions and you can't create
your own one and expect React to detect changes from it. So you must
access this object instead, it's harder to do it outside of a React
component, though. All routed components like MyFeatureComp receive
automatically the history object as prop. In its componentDidMount I
store that value in a global variable so I have access to it in the
api logic, but you'll need to come up with better approach I think, it's just for demo purposes.
Outside of this sample, error boundaries are nifty mechanism to handle errors in your render functions (not event handlers) (for either class or functional components). In my experience, I've used them mostly with the render-as-you-fetch strategy to incorporate them with the error boundaries. With that approach the request is effectively made in the render function as opposed to any callbacks like componentDidMount. But this is probably not the standard yet and official support will come probably in next major version, React 17.
I hope that helps, let me know if you have questions. ;)

How to make React ignore one route?

I'm working on a project that, for reasons too long to get into, at one point needs to redirect the user to the API. The problem is that the API and the React front end are on the same domain. So when the browser requests mydomain.com/api/blahblahblah, it gets picked up by React Router and never reaches the API.
I need React to ignore requests to that one particular route and to let the API handle it.
The app is hosted on Heroku so there's a chance this is a Heroku issue, not a React issue.
If you simply use the good old anchor tag (a tag) you should get the desired effect.
Also, you can trigger a redirect using JS:
<MyComponent onClick={ () => window.location.href = 'this/awesome/url/' } />

componentDidMount not called on HashRouter Route change

First of all: I know that this question has already been asked here and that there is also already a solution. Please read the whole post before marking this as a duplicate
I am using the HashRouter from react-router-dom and I have this simple route:
<Route path='/folder/:folderId' component={FileArea} />
The routing works fine but unfortunately my componentDidMount function is not being called after a route change. This is crutial for my application to work as I have to make an API Call every time the route changes to retrieve the corresponding data (according to the folderId url parameter).
I found a solution in the internet using componentWillReceiveProps and this would work fine for me but apparently this function will no longer work in future react versions: React Documentation
I also know that I could theoretically use static getDerivedStateFromProps(nextProps, prevState) but this function is called way to often and it would be rediculous to make an api call each time.
Is there an alternative for componentWillReceiveProps or some way to invoke componentDidMount?
you can use componentDidUpdate() life cycle hooks.
and to get the route data in your component use this.props.match.params.folderId in that method
and to stop continuous call add if condition it will only call whenever route change.
I hope it will work!!

Apollo graphql-connected React component isn't rerendering

I'm working on building an authentication mechanism over graphql, and I'm trying to figure out why a graphql-connected component isn't rerendering after relogin... for example:
At /users I have a react-apollo graphql-connected Users component that requests a list of users.
The server will return an authentication error if no token is provided; the component renders a <Redirect> to the /login route; after successful login, the Login component stashes the token and redirects back.
The Users component wrapper starts the graphql request and renders "loading..." in the meantime. When the graphql request succeeds, it rerenders and the users appear, yay.
If you Sign Out from that page, the Logout component at /logout discards the token then redirects back; the Users component's request gets the authentication error again and sends you to '/login'.
After another successful login, you're sent back to '/users'; again it starts a graphql request to the server (and renders "loading..."), but this time, when the request succeeds, the component isn't updated again.
I can see that the graphql request succeeds (and have watched in Chrome's debugger as the APOLLO_QUERY_RESULT action is handled by react-apollo's reducer and updates the state in the store).
I've tried to find where React is checking to see if the component's props have changed, but I'm enough of a React debugging noob that I haven't figured out where to find that code in the web inspector: maybe something I don't understand about how React is packaged for distribution.
I clear out the ApolloClient's store (by calling resetStore()) on both login and logout, since I don't want to accidentally reuse data from the other authenticatedness; however, removing these calls doesn't get rid of the problem. Interestingly (?), if I force the connection to bypass the cache by providing { options: { fetchPolicy: 'network-only' } } in the graphql() call, the problem goes away. (Not a viable solution - I'd like to benefit from the cache generally.)
I've built a stripped-down example: https://github.com/bryanstearns/apollo-auth-experiment
and you can see it in a CodeSandbox: https://codesandbox.io/s/m4nlpp86j (you'll probably want to access the running example from an independent browser window at https://m4nlpp86j.codesandbox.io/ because the sandbox editor kinda makes the web debug extensions act weird).
To fix this behavior, modify your graphql HOC to include notifyOnNetworkStatusChange in the options.
export const Users = graphql(usersQuery, { options: { notifyOnNetworkStatusChange: true } })(RawUsers);
I don't think you should have to do that -- I think data.loading is supposed to accurately reflect the status of your query regardless of that option being set to true, unlike data.networkStatus but it looks like it's a known bug.
As far as resetStore -- it doesn't actually wipe your entire store, but rather wipes away your store and refetches all your active queries. If you wanted to blow away your store, since you're already integrating Redux with Apollo, the easiest thing to do would be to create an action to do that.
You may also want to consider a session-based authentication mechanism, rather than relying on the client to persist a token. It's pretty simple to implement server-side, would not only involve less work on the client-side (don't have to remember to pass the token in with every request), and would let you keep your user logged in after they navigate away from the page.

Resources