Change document title after ajax call - javascript

I would like to be able to set the document title on each page of my React app. While I realise I can use document.title I'm not sure how to go about setting the title when it depends on data fetched via an async call. I'm using Redux for the server fetches.
Inside my component class I have:
componentDidMount() {
this.props.dispatch(fetchJob(this.props.match.params.slug))
}
but I'm not sure how to set the title once the call has finished?

You can use a callback to set the document title after the call is complete, as with any javascript promise. For more info, have a look at the then() method for Promises:
The then() method returns a Promise. It takes up to two arguments: callback functions for the success and failure cases of the Promise.
So your code would be:
componentDidMount() {
this.props.dispatch(fetchJob(this.props.match.params.slug)).then(() => {
document.title = "Your title";
})
}

I strongly suggest to use a middleware (you can create your own one) to manage things like: animations, logging, analytics, etc.
So you won't dirt the logic of your application.
If you want it being part of your application, implement such logic inside your component inside componentWillReceiveProps or componentDidUpdate (I suggest the first one), and update the slug. Of course, you should put a guard in this part of code, a condition of when to update your title

Related

How to get isLoading / isFetch on auto-refresh in RTK Query?

For example, the API has the getList() and deleteItem() functions. providesTags is configured to requery: after a deleteItem() request, a getList() request is automatically fired.
It is necessary to block the interface while the getList() request is in progress. How to do it?
I usually do this with isLoading, but it is part of a hook called on the component. And in the case of automatic re-request, the call occurs not in the component, but in the store
first, I miss understood your question
I think somehow you managed to call getList inside of the store.
you don't have access to the loading inside of the store because you have access to isLoading inside of Component, right?
first why you should do such a thing and if you must do it please provide some codes or explain more.
second I am assuming you do something like this
dispatch(api.endpoints.getPost.initiate()) then if so you should know RTK query have something called Matchers.
and throw this you have access to actions like matchPending, matchFulfilled and matchRejected.

Can I call APIs in componentWillMount in React?

I'm working on react for last 1 year. The convention which we follow is make an API call in componentDidMount, fetch the data and setState after the data has come. This will ensure that the component has mounted and setting state will cause a re-render the component but I want to know why we can't setState in componentWillMount or constructor
The official documentation says that :
componentWillMount() is invoked immediately before mounting occurs. It
is called before render(), therefore setting state in this method will
not trigger a re-rendering. Avoid introducing any side-effects or
subscriptions in this method.
it says setting state in this method will not trigger a re-rendering, which I don't want while making an API call. If I'm able to get the data and able to set in the state (assuming API calls are really fast) in componentWillMount or in constructor and data is present in the first render, why would I want a re-render at all?
and if the API call is slow, then setState will be async and componentWillMount has already returned then I'll be able to setState and a re-render should occur.
As a whole, I'm pretty much confused why we shouldn't make API calls in constructor or componentWillMount. Can somebody really help me understand how react works in such case?
1. componentWillMount and re-rendering
Compare this two componentWillMount methods.
One causes additional re-render, one does not
componentWillMount () {
// This will not cause additional re-render
this.setState({ name: 'Andrej '});
}
componentWillMount () {
fetch('http://whatever/profile').then(() => {
// This in the other hand will cause additional rerender,
// since fetch is async and state is set after request completes.
this.setState({ name: 'Andrej '});
})
}
.
.
.
2. Where to invoke API calls?
componentWillMount () {
// Is triggered on server and on client as well.
// Server won't wait for completion though, nor will be able to trigger re-render
// for client.
fetch('...')
}
componentDidMount () {
// Is triggered on client, but never on server.
// This is a good place to invoke API calls.
fetch('...')
}
If you are rendering on server and your component does need data for rendering, you should fetch (and wait for completion) outside of component and pass data thru props and render component to string afterwards.
ComponentWillMount
Now that the props and state are set, we finally enter the realm of Life Cycle methods
That means React expects state to be available as render function will be called next and code can break if any mentioned state variable is missing which may occur in case of ajax.
Constructor
This is the place where you define.
So Calling an ajax will not update the values of any state as ajax is async and constructor will not wait for response. Ideally, you should use constructor to set default/initial values.
Ideally these functions should be pure function, only depending on parameters. Bringing ajax brings side effect to function.
Yes, functions depend on state and using this.setState can bring you such issues (You have set value in state but value is missing in state in next called function).
This makes code fragile. If your API is really fast, you can pass this value as an argument and in your component, check if this arg is available. If yes, initialise you state with it. If not, set it to default. Also, in success function of ajax, you can check for ref of this component. If it exist, component is rendered and you can call its state using setState or any setter(preferred) function.
Also remember, when you say API calls are really fast, your server and processing may be at optimum speed, but you can never be sure with network.
If you need just data only at first run and if you are ok with that. You can setState synchronously via calling a callback.
for eg:
componentWillMount(){
this.setState({
sessionId: sessionId,
}, () => {
if (this.state.hasMoreItems = true) {
this.loadItems() // do what you like here synchronously
}
});
}

ReactJS - waiting for action to finish within componentDidMount

Code in question is below. I have an async UserActions call within componentDidMount, and immediately afterwards I am looking to user information from within the UserStore populated by this action. Clearly, I cannot rely upon UserStore.isLargeAccess() being defined. Is the best convention to place the code relying on the action within a callback, or am I missing some bigger design choice?
componentDidMount() {
this.changeListener = this._onChange.bind(this);
UserStore.addChangeListener(this.changeListener);
OrganizationStore.addChangeListener(this.changeListener);
// Fetch user info
UserActions.get(AuthStore.username);
// UserStore.isLargeAccess() is undefined here,
// because the previous action has not finished.
if (UserStore.isLargeAccess()) {
OrganizationActions.getUsers(this.state.organization);
}
if (UserStore.isGlobalAccess()) {
OrganizationActions.getOrganizations();
}
}
How it should to work (If I understand your flow):
You should register different callbacks for each of your stores (otherwise you don't know which store emit event)
You start some async work.
When async work is finished then it dispatch action with some data from async work
your stores UserStore and OrganizationStore listens for this action, and when they receive it, they do some job and emit change.
When they emit change, then they call callbacks from your component. In each callback you know which store invoke it, And therefore you know from what store get data.

Service call in Fluxxor / React.JS

I'm very very new to react.js and Fluxxor and I haven't done web development for a while. :)
I was wondering where to put server calls (JQuery $.ajax()) in my code?
My actions are only dispatching calls like:
var actions = {
onBlubb: function (data) {
this.dispatch(cmd.BLUBB, data);
},};
Then I have one store which does some changes and calls the emit function to update the view. The whole cycle works fine (view, action, dispatcher, store)
Now I guess I should put my ajax call in my store class. Let's say i call my store "blubbStore".
But I want my store classes to be testable. That means I have to put the ajax call in another store class which basically does the server call and ...
Approach 1) ... triggers a success/failed action. This action is handled in blubbStore
Approach 2) ... stores the service call response in properties. Then blubbStore calls "WaitFor" and reads the data from this "service-caller-store" once the service call is done.
I guess approach 2 is not possible, because the WaitFor does not await asynchronous calls? That means approach 1 would be the solution?
(And the actions should dispatch only messages. right?)
Thanks
In my personal view and experience - it's better to put async call in actions with this logic - image
In this way you can dispatch an event, calling loading screen for example and then, when data is recieved dispatch new change with data.
In the end I believe it's a personal choice, aim for the method that will help you handle code better.

What is the purpose of the React.addons.batchedUpdates API?

The React v0.12 release announcement included the following:
New Features:
* React.addons.batchedUpdates added to API for hooking into update cycle
However I cannot find any documentation for this API. What is its purpose?
Specifically, any chance that it has an equivalent of Ember.run()?
When responding to synthetic events like onClick and so on, component state changes are batched so lots of calls to this.setState for the same component will only result in one render.
If you are changing state in response to some other async callback (e.g. AJAX or setTimeout) then every call to this.setState will result in a render. You can wrap your work in batchedUpdates(..) to avoid this.
var React = require('react/addons');
var batchedUpdates = React.addons.batchedUpdates;
var request = require('superagent'); // AJAX lib
var req = request('GET', ...).end(function(err, res) {
// invoked when AJAX call is done
batchedUpdates(function(){
.. all setState calls are batched and only one render is done ...
})
});
The default batched update strategy is great for your average website. Sometimes you have extra requirements and need to deviate from that.
The initial reason this was made public is for a requestAnimationFrame batching strategy, which is better for games and sites that need to update often and in many places.
It's just an extensibility point to solve edge case issues.

Categories

Resources