I have written a whole application in ReactJS Client Side. I am able to accept /API on my react app URL using <BrowserRouter>
I am looking for a way to make a post request to my React App. Eg. When a user makes a post request to http://myreactapp.com , it should recognize the Post request and get the Post Body received from this call and I want to assign it one of the state before the React App loads.
I tried searching many things on BrowserRouter but I am not able to find 1.
Can someone help me direct towards the way to implement handling POST with body params.
I am open to only suggestions too and and not the whole code since I am kind of stuck thinking what to do next.
render((
<BrowserRouter>
<div>
<Route exact path="/"
render={() => (<App />)} />
<Route path="/find/:find"
render={(props) => (<App {...props} />)} />
</div>
</BrowserRouter>
), document.getElementById('root')
);
I tried with BorwserRouter but it seems it only accepts Get parameters and not Post body.
I have also heard of using NodeJS or express as the backend but can someone help me with modifying my current React code to convert to Express only for Post request and remaining everything remains same,
TIA!
Related
Edit: For anyone coming here from Google, here is a TLDR: The reason for this "issue" is that React uses client side rendering. A quick solution is to use the HashRouter component, an SEO friendly solution is to use server side rendering(SSR). I switched to using NextJS, an SSR React framework, and my concern is resolved. Pages refresh like normal, and favorites work as intended. Thanks to all in the comments.
Original Question:
I've tried to find the answer to this but maybe i'm not googling well enough. So I have a react app with multiple routes, one of the routes is /reset, I have routing set up in the App.tsx like so:
import { BrowserRouter as Router, Link, Route, Switch} from 'react-router-dom';
class App extends Component<IAppProps, IAppState> {
constructor(props: IAppProps) {
super(props);
this.state = {
loggedin: "false",
user: {
username: "",
email: ""
}
};
}
<Router>
<nav className="topnav">
<ul>
<li><Link to="/">Home</Link></li>
<li><Link to="/about">About Us</Link></li>
<li><Link to="/faq">FAQ</Link></li>
<li><Link to="/login">Login</Link></li>
</ul>
</nav>
<Switch>
<Route exact path="/">
<Home
text="This text was passed in as a prop"
/>
</Route>
<Route path="/login">
<Login
changeHandler={this.updateLoginInput}
/>
</Route>
<Route path="/register">
<Register
formSubmit={null}
/>
</Route>
<Route path="/forgotpassword">
<ForgotPassword
stateSetter={this.handleChange}
/>
</Route>
<Route path="/reset">
<Home/>
</Route>
</Route>
</Switch>
</Router>
Sorry for the bad indenting, the editor doesn't like tabs.
The links work fine but, when ever i manually type in the address bar localhost:3000/reset it just keeps spinning and eventually times out. Same with every other route in fact. I need this to work because im sending a password reset email that will contain a link to use, and currently it just keeps spinning when the link is clicked. What if someone were to favorite a route on my page like mysite.com/page1? It would keep spinning and then eventually time out.
I've tried to add a route on the server side with app.get() and a response.redirect() and redirect to the reset route, but Chrome blocked it as an unsafe redirect.
Does this functionality not work on localhost or is there something else i'm doing wrong?
My project using express for server and React for frontEnd. Routes are like this
<Router >
<Switch>
<Route exact path="/" component={HomeContainer} />
<Route path="/women" component={SectionContainer} />
</Switch>
</Router>
To serve these routes my server js has
server.get('*', function(request, response) {
response.sendFile(path.resolve(__dirname, '../public', 'index.html'));
});
Page url http://localhost:3000/women is working only on page refresh, first time click on url is just changing the browser url with no page update. But on page refresh it is working perfectly fine.
Please suggest what i am missing.
I was having similar issue. I found HashRouter helpful than the BrowserRouter:
import { HashRouter as Router } from 'react-router-dom'
Using HasRouter will be working fine as it keeps state on every history data changes.
I am building a client application using React and Redux, with server-side API endpoints set-up using Node.
For one feature I would like to send out a token in an email, then upon clicking a link (something like website.com/token?email=dave.example#something.com&token=3ad56gyhg) verify their token/email using a server-side API, before redirecting them to a particular page in React (using React Router).
I anticipate the Node API would look something like this:
app.get('/token', (req, res, next) => {
//code here.....
//goes and checks the email and token code match what is in the database
if (success) {
res.redirect('/welcome');
}
}
Once I've redirected to the appropriate React router endpoint, how do I provide state/props relevant to the user to any components? For example, I might want to use their email address on a page once their token has been verified.
ReactDOM.render(
<Provider store={store}>
<Router history={hashHistory}>
<Route component={App}>
<Route path="/" component={EntryPoint} />
<Route path="/welcome" component={WelcomeContainer} />
</Route>
</Router>
</Provider>,
document.getElementById('root')
);
Would I have to go down the isomorphic route and create a store on the server? Would the component need to go back and get an 'initial state' from the server?
You have a static HTML/CSS/JS server and you have a Node API. In this case, you can't 'template' the HTML that you send to the client. That means that you can only pass data to your react application via URL params.
app.get('/token', (req, res, next) => {
//code here.....
//goes and checks the email and token code match what is in the database
if (success) {
res.redirect(`/welcome/${encodeURIComponent(email)}`);
}
}
Then when your component loads, check for the query param:
ReactDOM.render(
<Provider store={store}>
<Router history={hashHistory}>
<Route component={App}>
<Route path="/" component={EntryPoint} />
<Route path="/welcome/:email" component={WelcomeContainer} />
</Route>
</Router>
</Provider>,
document.getElementById('root')
);
Alternative:
/token redirects to your webapp.
Your react application now picks up the email & token params and then makes an API request to /verify/token with the email & token parameters.
Your application handles the API request (which returns a success/fail) and then redirects internally to /welcome.
This is the way I've usually done this. The key is to make sure that when the user clicks on the verify link, they are taken directly to the webapp. The webapp does the API verification business.
I am facing tremendous issues trying to implement multiple entry points along with react router. The aim is to achieve using webpack to do something that is suggested by https://github.com/petehunt/webpack-howto.
So far I have currently set it up like this:
webpack.config.js
entry: {
entry1: __dirname + './entry1.jsx',
entry2: __dirname + './entry2.jsx'
}
routes.jsx
export default (
<Route path='/' name='app' handler={App}>
<DefaultRoute handler={entry1} />
<Route name='entry2' handler={entry2}/>
</Route>
);
Whenever this code is run to instantiate a instance of Router on the client
Router.run(routes, Router.HistoryLocation, (Handler, state) => {
React.render(<Handler />, document.getElementById('app'));
});
Node.js will try to run this code on the server which obviously fails as DOM is not available there. It will produce an error.
Is there any proper way to implement multiple-entry points with react-router?
I have done something similiar to this in a sandbox webpack-react-boilerplate repository I've been playing around with using react-router.
I believe the answer you may be looking for lies here where you need to use React.renderToString and/or React.renderToStaticMarkup in your server entry file as you rightly suggest, there is obviously no DOM on the server. You can see how the client entry point here differs to the server one.
What im trying to do is Have a Log In page, a Sign up page. The login and signup work fine, they just perform whatever was written in express using passport. However what I want to do is make a route '/dashboard'. I did so and it's just a dashboard component made up of other components like a navbar and body/content. How do I write it in react router in such a way that it only allows me to access the route /dashboard if the user is authenticated. In express I would write a function like this :
function isLoggedIn(req, res, next) {
//if user is authenticated in the session, carry on
if (req.isAuthenticated())
return next(); //cuz we want to move on incase we're stuck here
//if they arent redirect them to the home page
res.redirect('/');
}
However I didn't even write in the dashboard route in express. I only did it in react-router. My component hierarchy is like this right now
<App/>
<Dashboard/>
<NavBar/>
<NavMenu/>
<Body/>
<Login/>
<Signup/>
<About/>
And my routing is like this :
<Route>
<Route name ="signup" path="/signup" handler={Signup} />
<Route name ="login" path="/" handler={Login} />
<Route name ="app" path="/dashboard" handler={App} >
<Route name ="logout" path="/logout" handler={NavMenu} />
</Route>
</Route>
I don't understand if i'm grasping the concept right, but from what the webpage is displaying it doesn't seem like it. So basically at localhost:3000/ comes up the log in page, and I can toggle between that and the signup page completely fine, when the log in button is hit it uses express to login (it can use react-router to do it as well correct?), on success it goes to /dashboard (res.redirect('/dashboard') in express). It also seems as routes handled by react router has that single page app feel, whereas express it feels like i'm going to a new webpage (I'm guessing that happens because of react-router just changing the url and rendering the component we want?). In my NavMenu component I link the logout button Logout however the url changes to localhost:3000/logout and nothing happens.
I nested it under login so to get to dashboard and it's routehandler it has to go through the login.
<Login>
<App>
<RouteHandler>
<dashboard../>
<data../>
<etc../>