Modern Full-Stack Development



Download 5,64 Mb.
Pdf ko'rish
bet53/107
Sana06.08.2021
Hajmi5,64 Mb.
#140576
1   ...   49   50   51   52   53   54   55   56   ...   107
Bog'liq
Modern Full-Stack Development Using TypeScript, React, Node

 Back  to the Code!
Now that you have an idea of what state is in play, we can get back to the code in main.tsx:
baseComponent.state.showHidePleaseWait(true);
Once the UI is built, the next task that must be accomplished is to call the server 
and get a list of mailboxes available for the account and a list of contacts the user has 
created. Any time we call the server, we’re going to display a “please wait” popup, so the 
user knows something is happening. This will also serve the purpose of blocking the UI 
for a moment so that the user can’t go and do something that causes problems while the 
server works. The showHidePleaseWait() method of the state object, the first of the state 
mutator methods we’ve encountered, does this for us:
showHidePleaseWait : function(inVisible: boolean): void {
  this.setState({ pleaseWaitVisible : inVisible });
}.bind(inParentComponent)
You must remember that with React, you don’t directly tell components to do 
things. Instead, you mutate state in some way, using the setState() method on the 
component that holds the state, which causes React to repaint the pertinent parts of the 
UI as needed. In this case, to show the please wait popup, all we need to do is update 
the pleaseWaitVisible state attribute, setting it to true. React will then redraw the UI, 
and what will happen, something you’ll see later, is that the popup element will now 
be set to visible. This will make sense when we look at the MainLayout.tsx file, but just 
keep in mind for now that pleaseWaitVisible is set to true when we want the please 
wait popup to be shown and false when we want it hidden and that React will see that 
change in state and redraw the screen as needed. That’s the key thing right now.
The little problem I alluded to earlier is that since we are limited to calling the 
setState() method on the component that contains the state object, any code that tries 
to call it must execute within the context of that component. When we define a separate 
object for state as I did in order to break it out into its own source file, the this reference 
in the methods inside state won’t be what we need. In other words, any method inside 
the state object won’t have access to setState() because its execution context, at least in 
some instances, won’t be the BaseLayout component.
That’s where the bind() statements come in, and you’ll see these on every function 
in the state object. When the state object is constructed via the call to createState(), a 
reference to the BaseLayout instance was passed in. That’s what we bind all the mutator 
Chapter 9   Delivering the gooDs: MailBag, the Client


235
functions to. That way, they will always have access to setState() as we need. Note that 
if any of them needs to touch the state object itself, which they obviously would need to 
in at least some cases, they can do so by accessing this.state, since components always 
expose their state via that property.
With the please wait popup showing, we can now call the server:
async function getMailboxes() {
  const imapWorker: IMAP.Worker = new IMAP.Worker();
  const mailboxes: IMAP.IMailbox[] = await imapWorker.listMailboxes();
  mailboxes.forEach((inMailbox) => {
    baseComponent.state.addMailboxToList(inMailbox);
  });
}
We know that getting a list of mailboxes is an IMAP operation from our look at 
the server code, and since the IMAP Worker class on the client seeks to mimic that 
API that is exposed by the server to the IMAP Worker class there, it makes sense that 
we’d be calling IMAP.Worker.listMailboxes() here too. And the code looks almost 
identical to the endpoint handler function code on the server as a result. We’ll look at 
the client-side IMAP close a bit later, but I think you’ll find it rather trivial. The bottom 
line, though, is that we get back an array of mailboxes, and we then iterate them and 
call the addMailboxToList() method on the state object (which we can do because we 
have a reference to the BaseLayout component via the baseComponent variable). That 
will update the mailboxes array in state, causing React to render the screen to show the 
mailboxes on the left.
And addMailboxToList() method is the next state mutator we’ve hit:
addMailboxToList : function(inMailbox: IMAP.IMailbox): void {
  const cl: IMAP.IMailbox[] = this.state.mailboxes.slice(0);
  cl.push(inMailbox);
  this.setState({ mailboxes : cl });
}.bind(inParentComponent)
First, you have always to remember that when you call setState(), you should never 
pass references to objects in state. That may sound weird, but it’s easy to understand 
when dealing with arrays, as we are here. Your first inclination would be to directly push 
Chapter 9   Delivering the gooDs: MailBag, the Client


236
inMailbox into state.mailboxes and then try to call this.setState({this.state.
mailboxes}). Everyone tries that at first because it seems reasonable! However, it won’t 
work because what you pass into setState() replaces what’s in state at the time, and 
trying to do that with what’s already there… well, let’s just say React won’t like you very 
much!
Instead, we make a copy of the array via slice(0), then push the new mailbox into 
that copy, and finally pass that copy to setState(). Now, everything works as expected. 
Note that you only have to do this sort of copying/updating/setting when dealing with 
objects and collections.
If you’re paying attention so far, you will have noticed that we haven’t actually called 
the server to get the list of mailboxes yet, we’ve only defined a function to do so. That’s 
because the function that calls imapWorker.listMailboxes() must be marked async 
since we’re await’ing the response. getMailboxes() is marked async, so now we need to 
call it:
getMailboxes().then(function() {
  async function getContacts() {
    const contactsWorker: Contacts.Worker = new Contacts.Worker();
    const contacts: Contacts.IContact[] = await contactsWorker.listContacts();
    contacts.forEach((inContact) => {
      baseComponent.state.addContactToList(inContact);
    });
  }
  getContacts().then(() =>
    baseComponent.state.showHidePleaseWait(false));
});
We don’t want to get the list of contacts until the list of mailboxes is done so that 
we know that all server calls are done before the please wait popup is hidden, so we 
use the then() syntax to chain them. Inside the then() callback, another function 
is defined, getContacts() this time, for the same reason: async/await usage. Once 
defined, we can call getContacts() and again use the then() syntax so that we can call 
showHidePleaseWait(), passing false this time, to cause React to hide the please wait 
popup.
Chapter 9   Delivering the gooDs: MailBag, the Client


237
The addContactToList() state mutator method is used in there, and it’s virtually 
identical to addMailboxToList():
addContactToList : function(inContact: Contacts.IContact): void {
  const cl = this.state.contacts.slice(0);
  cl.push({ _id : inContact._id,
    name : inContact.name, email : inContact.email });
  this.setState({ contacts : cl });
}.bind(inParentComponent)
In this case, I’ve constructed the object push()’ed into the contacts array explicitly, 
not for any particular reason other than to show that you can. If you wanted the client 
contact objects to have different fields than the server-supplied objects for some reason, 
this is how you can do that translation.

Download 5,64 Mb.

Do'stlaringiz bilan baham:
1   ...   49   50   51   52   53   54   55   56   ...   107




Ma'lumotlar bazasi mualliflik huquqi bilan himoyalangan ©hozir.org 2024
ma'muriyatiga murojaat qiling

kiriting | ro'yxatdan o'tish
    Bosh sahifa
юртда тантана
Боғда битган
Бугун юртда
Эшитганлар жилманглар
Эшитмадим деманглар
битган бодомлар
Yangiariq tumani
qitish marakazi
Raqamli texnologiyalar
ilishida muhokamadan
tasdiqqa tavsiya
tavsiya etilgan
iqtisodiyot kafedrasi
steiermarkischen landesregierung
asarlaringizni yuboring
o'zingizning asarlaringizni
Iltimos faqat
faqat o'zingizning
steierm rkischen
landesregierung fachabteilung
rkischen landesregierung
hamshira loyihasi
loyihasi mavsum
faolyatining oqibatlari
asosiy adabiyotlar
fakulteti ahborot
ahborot havfsizligi
havfsizligi kafedrasi
fanidan bo’yicha
fakulteti iqtisodiyot
boshqaruv fakulteti
chiqarishda boshqaruv
ishlab chiqarishda
iqtisodiyot fakultet
multiservis tarmoqlari
fanidan asosiy
Uzbek fanidan
mavzulari potok
asosidagi multiservis
'aliyyil a'ziym
billahil 'aliyyil
illaa billahil
quvvata illaa
falah' deganida
Kompyuter savodxonligi
bo’yicha mustaqil
'alal falah'
Hayya 'alal
'alas soloh
Hayya 'alas
mavsum boyicha


yuklab olish