I am using the server side rendering to the app, I want to load some data through the API before the page renders the at server side.
As I found the componentWillMount is called before rendering both server side and client side, but it doesn't executing the ajax code. Says $ is undefined,
Please anyone tell me what is the way to load the data before rendering the page.
This will be a generic answer because of the lack of details in the question. But I hope it sheds some light on the subject.
Based on my personal experience, if you're server rendering react you better have a "Controller" out-most component, that would deal with the whole state and everything beneath it should be mostly controlled or not depend on Ajax to load data at all. If you're using Redux, for instance, this "controller" component would be the Provider. This is because it's much easier for 1 component to deal with server vs. client than all of them.
Now, the outer "controller" component should know whether or not it's on the server and load data differently accordingly. One way to do that is to check if "window" is defined. That is: If you're on the server, don't use Ajax al all to load the initial state.. But if you are on the client, then use Ajax.
Now you have one last problem. When you do server rendering, you don't want the client to round-trip to the server to get the same data it already has. In order to prevent that, render a script block to be executed on the client, that contains the initial state and DO NOT do the Ajax if this variable is set. Like this:
<script>
window._serverState = {...}
</script>
Another thing.. I personally don't use $ for Ajax I don't think React and jQuery should be used together. Check out Axios.
Generally It is not advisable to make ajax call in componentWillMount. Because just after the componentWillMount rendering happens so rendering has to wait till the ajax call gets completed and gets new data.
It's better to get the rendering done for the first time with empty state data lets say
data:[]
and make ajax call in componentDidMount, this is the place where you can perform dom manipulation and send ajax request.
componentDidMount() {
sendAjaxRequest()
.then(
(newDataFromServer) => {
this.setState({data : newDataFromServer });
});
}
After new data is fetched from server set the state with new data
this.setState({data:newDataFromServer});
This will cause the re-rendering to happen with latest data fetched from server and new state changes will be reflected.
Related
Suppose I am consuming an API and getting it's data as:
{USA:12,IND:21,NEP:90,ENG:81}
after sometimes it's data changes to :
{USA:2,IND:1,NEP:0,ENG:1}
and so on...its data is continuously changing, I have created an table in react which shows data for these countries and is updating the table's data every time there is change in data.
Now, I want to know how does table update the data in real time without reloading the page or clicking any button, but by itself.
Is it listening to API every time i.e. making API call continuously, and it fetching data continuously and when there is change in data updates the component or what actually is happening?
This was a question asked to me during interview for which I told that it is continuously calling API and when data changes it updates the table but I'm not sure if this is correct answer or not … or how it actually happens?
If anyone could provide me some article that I can refer to or provide me explanation that would be great.
If anyone needs anymore information please let me know.
For React Applications, there are three ways to get real-time updates.
HTTP Polling
Server Side Events
WebSockets.
There are pros and cons to each approach.
HTTP Polling: Pros: Easier to implement Cons: The server is overloaded.
Server Side Events: Pros: Easier to implement Suited for publish/subscribe model. Cons: Two-way communication is hard.
WebSockets: Serverside support or third-party integration is needed.
Here is more information about different methods to get Real Time Updates.
The question was likely assessing if you knew how React's virtual DOM model works.
When the new data is downloaded (callback from fetch or xmlhttprequest), a setState call (or equivalent hook function) is likely called on a component - passing the json with it.
React will then call the render method of the component (or just invoke the function of the pure component). This render function will reference the state to return a tree of elements. This will in turn cause React to update its virtual DOM, compute a diff with the previous version, and apply those diffs to the actual HTML DOM for the browser. If there's no actual change to the DOM since the last render, then no actual updates are done to the browser DOM. There's probably optimizations and details I'm missing, but that's what I would be looking for in an interview.
Some links that are useful to this.
Virtual DOM and Internals
Reconciliation
I am learning how to use Reactjs and I read the following post :
https://reactjs.org/blog/2018/03/27/update-on-async-rendering.html#fetching-external-data
When componentWillMount is used, it is written that The above code is problematic for both server rendering (where the external data won’t be used) and the upcoming async rendering mode (where the request might be initiated multiple times).
I do not understand :
How the request might be initiated multiple times because
componentWillMount is used only one time.
Why componentDidMount solves this problems. For the server rendering,
the external data won't be used also in the first render call.
According to the React docs, changing your component’s state in componentWillMount will not trigger a re-render. This means that if you make your AJAX call and set the response in your component state, it will not re-render, which means you won’t see your data in the DOM. (Remember that the component was initially created with an initial state which most likely didn’t have the data from your external data/AJAX call response)
You could argue that wouldn’t it be better to do my AJAX call to pull external data before the component mounts for the first time?
It wont be better because you don’t know how much time it will take to do your AJAX call. Your AJAX request could take longer to get the data than the time it takes the component to mount and therefore your data does not show up on your DOM as the component has already rendered and there is no re-rendering happening. Your AJAX request could take longer for any reason - your user is on mobile and has slow internet, some issue with your server is making it slow to return responses, etc...
Best thing to do is make your AJAX call in componentDidMount and make your component handle empty data (probably display a loading spinner) until your AJAX request returns the data, sets it to the component state and triggers a re-render! :)
If you read further down they explain a bit more why componentWillMount is problematic.
The above code is problematic for both server rendering (where the
external data won’t be used) and the upcoming async rendering mode
(where the request might be initiated multiple times).
But these may be rendered moot as react is essentially deprecating that lifecycle function come react 17, and thus currently is renamed to UNSAFE_componentWillMount and not recommended for use, but instead use componentDidMount to make your async data fetches.
Why does componentDidMount fix this?
Because the server is pre-rendering the components/JSX, but you don't want the component to fetch its data until after it is actually mounted and running in a browser.
react component lifecycle docs
I created server side rendering with approach described in redux's official site, everything is great, but on client side it rendering components again, and this is not good I think. I am passing same state from server to window.__STATE__ variable and passing this to my client side createStore method as initial state, but it rerendering again.
Also please write in comments which part of code is needed to you, if so.
I am not providing since it is very similar to official page instructions code and there is no errors, just issue with rerendering, but as I understand it is not connecting to virtual DOM.
Please help me find valid way for handling this task.
Take a look at this example from the ReactGo project: https://github.com/reactGo/reactGo/blob/master/app/client.jsx#L22
They use a function onUpdate that has the conditional
if (window.__INITIAL_STATE__ !== null) {
window.__INITIAL_STATE__ = null;
return;
}
which prevents a duplicate fetches if __INITIAL_STATE__ is already defined. Your components rerendering may have something to do with the duplicate fetching.
Perhaps I am not understanding what you mean by re-rendering, but it is supposed to "re-render" on the client again. The way isomorphic works is that it renders the HTML on the server, and then the payload includes the initial state as well has the HTML markup - this way the browser "appears" to have faster page load times - since the UI is rendered even before the script is executed. Now once the HTML parsed and the script runs, React internally builds the virtual DOM and then compares it to the server generated DOM and wires up event listeners etc. It does not however, do a full re-render in that no new DOM elements should be created. If for any reason the client run of your React render results in a virtual DOM that is different from the generated server DOM, React will give you a warning.
"Warning: React attempted to reuse markup in a container but the
checksum was invalid. This generally means that you are using server
rendering and the markup generated on the server was not what the
client was expecting. React injected new markup to compensate which
works but you have lost many of the benefits of server rendering.
Instead, figure out why the markup being generated is different on the
client or server:"
I am building an isomorphic app with React that must support users without JS.
I am new in this technology and I have a basic doubt:
The server can store the components states to emulate what React does in the client-side?
I imagine this flow when the user dont have JS:
The user click a button and send a request to the server.
The server recovers the state of the app and makes changes in it.
The components listen this changes and are rendered again.
Is it correct?
Assuming that you're using react-router :
The server aims to initialize your state, to provide it the default minimum values necessary to make your application work while getting an url.
For example, if you have an application in which you want to display a user list, let say on /users URL, when you'll send your first request, the server will store the users in the react state.
After that first load, you'll be working on the client side using react-router, and making XHR request.
However, if you refresh your page, the process will start again : first load initializing the state and then client side navigation.
EDIT : Explanations =>
When you want to use react on the server, this means that you use a Nodejs server. The fact is that react-dom provides a method called renderToString that transform a react jsx component into standard HTML.
This aims to load the first call faster
Why ?
When you load a "big" JS application on the client, you have some delay time, the time your browser needs to download your JS bundle.
Server side rendering aims to avoid that behaviour, or at least, to gives the feeling that the app starts faster.
In no case you can only use react, even if you use your server side renders. Why ? . Because your events on buttons, or asynchronous load on client, or keypress are in JS language.
I was wondering how it's the best way to render server-side (without rendering this on the client) AND handle the state changes coming from async queries.
Ideal Example:
A server gets a requests to generate an HTML
The server 'requires' a react component, passing some props
The react component renders in the server, but it has to do an
Ajax/Socket query to get some info. The event is sent and the
response comes later.
The react component changes the state, changing the output
The HMTL generated is ready and with the latest state changes.
What's happening here is that ReactDOM.renderToStaticMarkup(), as expected, doesn't wait for the component to finish the state changes (in this case, wait for the data and re-render).
To clarify:
There is no client here, it's not the typical SSR. I just need the full HTML on the server so I can do other actions later. The problme here is how to wait for those async calls and use the same component that I use on the client (it has states and some setStates).
I'm assumming then only way is to have stateless components that just receive the props (doing all the socket handling previously and passing the data to each component). Right now the components are plain React, no Redux involved (that's why they are not stateless).
Any other idea/approach?
Thanks!
If there's no client involved, then whatever happens, you'll need to wait for all the data to load before rendering.
If possible, I'd suggest moving all async work outside of your component tree. Then passing it into the root component to distribute to the children (via props) when you call render.
createAsyncState(function(state) {
// generate the markup for this component tree
const markup = ReactDOMServer.renderToString(
<Component state={state} />
);
// serve the markup to the client
res.end(markup);
});
If you want to use the same component on the client too, then all you need to do is make sure your createAsyncState equivalent also works in a browser.