React POST to Node Server and handle JSON response - javascript

I am new to React so I am trying to understand how all this works together.
Is there a way to change the component that is rendering for another component after getting a status 200 from a node server?
For Example. I am doing a POST http request from a signup pageto my node with express server. The server response with a json object to my front end. Which Now I want the the profile component/page to render rather than staying at the signup page. This allows me to use the Json data and render it on the profile page. Is this possible? If you have another alternative I am open for suggestions too.
Thanks everyon.
Note:
I am using react router to control the different routes.
My node server is setup with passport to handle the singup.

You basically need to manage the state of your application (the user is connected / not connected). Then you can wrap your page inside a component managing the fact that user is connected or not.
Suppose you set user_is_logged as true if the login is successful. You can do something like :
var PageWrapper = React.createClass({
render : function() {
// user_is_logged is true if user is correctly logged
// LoginPage is the authentication form
var pageContent = user_is_logged ? this.props.children : <LoginPage />;
return (
<div>
<Menu />
<div className="container">
{pageContent}
</div>
</div>
);
},
});
var MyPage = React.createClass({
render : function() {
return (
<PageWrapper>
<div>content of page...</div>
</PageWrapper>
);
},
});
And re-render the page in the ajax callback :
ReactDOM.render (<MyPage />, document.getElementById('my-app'));
It works also with React router.

Please, take a look at Redux Architecture available at http://redux.js.org/
Understanding its concepts will make it clear to you the matter.
Then, go to the Advanced Topics of Redux and you will understand how asynchronous requests interact with Redux Components - (http://redux.js.org/docs/advanced/
Hope this helps.

Related

Does React block users from finding components behind login?

I'm new to React and am working on an app that requires user authentication. I have my authentication working fine, basically with redux keeping track of an isSignedIn piece of state, which defaults to false. If false, the user is shown a login form, and if true, the user is shown whatever else they need to see. The login form uses axios to send a post to a server-side authentication script, which responds with a JSON object that includes whether the user is valid or not, and the reducer sets isSignedIn accordingly.
I'm curious though, since the entire app is client-side javascript, can't a nefarious user somehow un-pack the script and modify it locally so they can see the components that normally don't render unless logged in?
Some relevant code snippets from the main App component...
render:
render(){
return (
<div className="ui container">
{
this.props.isSignedIn &&
<Navigation pathname={this.props.pathname} />
}
{
!this.props.isSignedIn &&
<Login />
}
</div>
);
}
mapStateToProps:
const mapStateToProps = (state) => {
return {
isSignedIn: state.isSignedIn
};
};

What benefits does React suspense have?

I know React suspense is new and hasn't been officially released for production yet but I was wondering what the main benefits of it are/or using it would be?
I can't see anything it does as being "new" or replacing something that doesn't already exist?
I know it allows me to load stuff from top to bottom but I can do that anyway in react using my own components
can anyone give me some ideas as to what it may be good for?
it has several benefits to use:
it makes code splitting easy
(with new usecase) it makes data fetching so easy! Read this
it just suspends your component rendering and renders a fallback component until your component makes itself ready to show, by that you can create a skeleton flow for your async components so easily event with a simple UI ( imagine instead of created a loading login by useState Api or something else )
these were just simple benefits of Reacts Suspense/lazy api.
First of all, I would like to mention that Suspense is officially released since React 16.6. It is production-ready and it is not limited only to code-splitting. Any asynchronous code can be integrated with it.
As of the benefits, consider the following use-case:
We have several components that all use some asynchronous code inside them (like fetching remote resources)
We need to display a loading indicator until all components are finished doing their job
We need to display an appropriate error if some of the components have failed to do their duty
Old way
The good old way of doing this would be:
Create a wrapper component for showing loading indicator and error messages
Keep track of loading and error state inside of each component and inform the wrapper component of state changes
Does this all look like unnecessary, hard to change boilerplate? Yes, it does).
New way
React introduced the Suspense component and Error Boundaries to eliminate this boilerplate and to declaratively describe the desired behavior.
Check this out:
<Exception fallback="An error has occured">
<Suspense fallback="Loading...">
<OurComponent1 />
<OurComponent2 />
<OurComponent3 />
</Suspense>
</Exception>
Example
Suppose we want to fetch users' data from the remote resource.
const fetchUsers = async () => {
const response = await fetch("https://jsonplaceholder.typicode.com/users");
const users = await response.json();
console.log("Users data", users);
return users;
};
I will use makeSuspendableHook to integrate our asynchronous fetch within <Suspense> and Error boundary.
const useUsers = makeSuspendableHook(fetchUsers());
In our component, all we should care about is the actual data and its representation.
const Users = () => {
const users = useUsers();
return (
<div>
List fetched users:
<ul>
{users.map(({ name }) => (
<li>{name}</li>
))}
</ul>
</div>
);
}
Finally, I will use Exception as an Error Boundary implementation to stitch everything together.
export default () => (
<Exception fallback="An error has occurred">
<Suspense fallback="Waiting...">
<Users />
</Suspense>
</Exception>
);
Play with web example at codesandbox.io
Play with native example at snack.expo.io

Wait for 2 API's fired by different components to complete before firing another API

The main navigation of my app needs to call a loggedInUser API to allow me to render different links depending on whether or not the user is logged in. This API is also used in many other parts of my app. I am using Redux for state management so once this API has fired I can get the data via the Redux store from any connected component.
I also have a ContentPage component which onEnter loads content via the loadContent API. ContentPage is a container component which is connected to the Redux store.
Finally, I also have an isFavourite API which takes the content ID and type (returned from the loadContent API) and allows me to toggle a 'favourite' button on the page depending on the response. This API should only be called after both the loadContent and loggedInUser API's have both fired (I don't need to bother firing the API if the user isn't logged in).
The code below works fine if the loggedInUser API completes before the loadContent API, but not the other way round. I'm struggling to think of the cleanest way to make it so that the order in which the API's return data has no impact on the logic. If the API's were both fired from the same component then I could do something like this (as I'm using Fetch for API calls)...
<Route
path={'Content/:id'}
component={ContentPage}
onEnter={(nextState) => {
// Needs to be synchronous
store.dispatch(loadSession(nextState.params.id)).then(() =>
store.dispatch(getLoggedInUser()),
);
}}
/>
...but as they are independent I don't know how best to approach.
import React from 'react';
import { Route } from 'react-router';
import configureStore from './store/configureStore';
import { getLoggedInUser } from './actions/userActions';
import { loadContent } from './actions/contentActions';
import App from './components/App';
import ContentPage from './components/ContentPage';
export const store = configureStore();
export const routes = (
<Route
path={'/'}
component={App}
onEnter={() => store.dispatch(getLoggedInUser())}
>
<Route
path={'Content/:id'}
component={ContentPage}
onEnter={nextState => store.dispatch(loadContent(nextState.params.id))}
/>
</Route>
);
This is a simplified version of my ContentPage component.
class ContentPage extends Component {
componentWillReceiveProps(nextProps) {
if (this.props.content.id !== nextProps.content.id) {
// If the loggedInUser API hasn't yet fired then this if statement will never return true
if (this.props.loggedInUser.id) {
// I only want to fire this API if both the loggedInUser API and the loadContent API have both fired
this.props.actions.isFavourite(nextProps.content.id, nextProps.content.type);
}
}
}
}
Why not just have a var called stagesCompleted = 0 or something, where each stage +=1 to it on each API call. Then have a conditional if(stagesCompleted == 2){} fire your code and reset the stagesCompleted var. that way you can add or reduce how many actions are needed before it fires too.
So back in the dark ages I built an ecommerce store with a single Perl cgi script for each page of the site. Each script when run would collect the data it needed (it's "database" was a bunch of files it read/wrote including a tab delimited products list), then it would write out the html for the page and serve it to the browser. I think it's one reason I like React, it does the same, just much more efficiently!
So what's my point? This is how you should think of your react app. It has state possibly consisting of a store such as Redux, and the state held in it's components, and from that state it builds html. If that state changes, then it rebuilds the html accordingly.
So for your example the whole site should be renderable with no session, with a session but no content, with session & content but no favourite. The components should not wait for the content they need. If it's not present then they render null, or a loading message, or maybe placeholder data. When the data they rely on changes, then they re-render accordingly.
Think of your site as frames in a movie, each with it's own unique app state. If you were to lay it all out you could have a screenshot for every possible variation in your state, perfectly renderable by your app.

React router not reloading Component when changing url params

I know that it's not a default behaviour / feature of react-router to help us reload easily the current component but I really need this in my application.
My application deals with products. I have a product list that I can load, and when I click on an item, it displays the concerned product details.
On that page, I have related product links that load the same component, but with another product details, located at
<Route path="/products/:id/details" component={ProductDetail} />
I m fetching data in my componentWillMount, and it seems that if I only change the URL, a new component is NOT mounted, and so, I m always having my old data displayed, without fetching anything.
As a beginner using React, I'm looking for some help, or some tricks to reload the component concerned by that page. I mean being able to reload the ProductDetail with the good product.
I tried to look around with componentWillUpdate (a method in which I can see that the router URI changes :D) but I can't setState inside of it to make my component reload (it doesn't seem to be a good practice at all)
Any idea how can I make this work ?
EDIT : According to the first answer, I have to use onEnter. I m now stuck with the way of passing state/props to the concerned component :
const onEnterMethod = () => {
return fetch(URL)
.then(res => res.json())
.then(cmp => {
if (cmp.length === 1) {
// How to pass state / props to the next component ?
}
});
};
The way to handle it depends if you are using flux, redux or however you want to manage your actions. On top of it I would try to make use of onChange property of Route component (check React router docs):
<Route path="/products/:id/details" component={ProductDetail} onChange={someMethod} />
And then in the someMethod create the action if you are using redux or however is done in flux.
The redux would be:
<Route path="/products/:id/details" component={ProductDetail} onEnter={onEnterHandler(store)} />
And the onEnterHandler with the redux store:
function onEnterHandler(store) {
return (nextState, replace) => {
store.dispatch({
type: "CHANGEPRODUCT",
payload: nextState.params.id
})
};
}
And then in your ProductDetail component you would print the new information (It would require a bit more of learning in redux and redux-sagas libraries to complete that part).
Keep in mind that React is just the view part, trying to solve all those problems using only react is not only not recommended but also would mess up your code.

Update application state from child in React + Flux

UPDATE It turned out my whole approach was wrong. As the accepted answer suggests, a good starting point is the TodoMVC app built with React + Flux and hosted on GitHub.
I am building a very small React + Flux app for learning purposes. At the moment it consists only in a login form and in a content (that actually just shows the username). I'm planning to have the application component as the only stateful component in my app, that will send its state to the children as props. But I can't figure out what's the best practice to update the application state from a child (in my case, the input form). I think I can probably bubble it up along the hierarchy, but it really seems a bad practice. Also, should I save the logged in username in the stores?
Here's a basic example of what I mean:
var LoginForm = React.createClass({
_onSubmit : function(e) {
e.preventDefault();
var username = this.refs.username.getDOMNode().value.trim();
if(!username) return;
alert(username);
this.refs.username.getDOMNode().value = "";
return
},
render : function() {
return (
<div>
<form onSubmit={this._onSubmit}>
<input
type="text"
placeholder="Insert username"
ref="username"
/>
<button type="submit">Login</button>
</form>
</div>
);
}
});
var Header = React.createClass({
render : function() {
return (
<div className="header">
<LoginForm />
</div>
);
}
});
var Content = React.createClass({
render : function() {
return (
<div className="content">Welcome, [username]</div>
);
}
});
var MyApp = React.createClass({
render : function() {
return (
<div>
<Header />
<Content />
</div>
);
}
});
React.renderComponent(
<MyApp />,
document.body
);
I have set up a JSFiddle here with this example, my goal is to substitute [username] with the alerted string.
im sorry but i didn't see any flux's architecture in your code yet :) for a high level implementation explanation, assuming you have all 3 basic structure of flux, namely action, dispatcher, and store.
in the _onSubmit in LoginForm component, you should trigger the action to perform the login, and then the event will go through the dispatcher and pass to store.
from the store, it will perform the login (and here you save the [username] information), and then trigger an event (for example change). This event will be registered and listening by the Content component in the componentDidMount. Upon listened the change event, you should able to get the username information from the store. This is a good example for the flux

Categories

Resources