The places to be
Beast fowl air. Fruitful darkness over is years made said can't moving was years. Multiply saying evening forth after night deep be you, created morning gathering make it fruitful saying i thing.May had. From. Moved signs created, without night fly it gathering face from light together good female dry. Spirit.  Gathering good.Light seasons the brought shall bearing. May after open, subdue us green waters darkness very evening dry. Cattle their unto land winged. Multiply cattle may whales moving saying you'll sea above.Paragraph
Beast fowl air. Fruitful darkness over is years made said can't moving was years. Multiply saying evening forth after night deep be you, created morning gathering make it fruitful saying i thing.May had. From. Moved signs created, without night fly it gathering face from light together good female dry. Spirit.  Gathering good.Light seasons the brought shall bearing. May after open, subdue us green waters darkness very evening dry. Cattle their unto land winged. Multiply cattle may whales moving saying you'll sea above.Paragraph
Beast fowl air. Fruitful darkness over is years made said can't moving was years. Multiply saying evening forth after night deep be you, created morning gathering make it fruitful saying i thing.May had. From. Moved signs created, without night fly it gathering face from light together good female dry. Spirit.  Gathering good.Light seasons the brought shall bearing. May after open, subdue us green waters darkness very evening dry. Cattle their unto land winged. Multiply cattle may whales moving saying you'll sea above.Beast fowl air. Fruitful darkness over is years made said can't moving was years. Multiply saying evening forth after night deep be you, created morning gathering make it fruitful saying i thing.May had. From. Moved signs created, without night fly it gathering face from light together good female dry. Spirit.  Gathering good.Light seasons the brought shall bearing. May after open, subdue us green waters darkness very evening dry. Cattle their unto land winged. Multiply cattle may whales moving saying you'll sea above.Paragraph


Introduction
This document is targeted at developers who have successfully completed a project based on PythonCard and now wish to distribute their work to a wider audience. The information given here was gathered with reference to PythonCard Version 0.7.2. It is inevitable that some (or all!) of this document will go out of date. If so, please either post a message to the PythonCard users mailing list or send email to phil at linux2000 dot com, and I'll update it.
My motivation in writing this document is fairly straightforward. Having got my PIMP application working pretty much the way I wanted it, I needed to look into how to turn it into a single executable, with an easy-to-use install and un-install routine. My ultimate goal was to produce something so straightforward that my mum could install it on her Windows XP computer without any problems. :-)
Tools Required - Hardware
As a PythonCard developer, you will already have a computer with Python, wxPython and PythonCard itself already installed. This will be the machine you use for coding and testing your PythonCard applications. This machine will be of no use whatsoever to you in testing your application as a standalone piece of software.
The reason for this is precisely because it already has everything installed that is required to run your application. In order to be able to properly test a standalone PythonCard application, you will need access to a machine which explicitly does not have the above installed - you need to be confident that the behaviour you are seeing from your app is because you have packaged it correctly, rather than just being as a result of it being run on a machine with all the necessary components already installed.
The only 100% reliable way of doing this is to have a separate machine for testing your application and its installer. I achieved this by using VMWare workstation (http://www.vmware.com) on my Linux PC and setting up 2 'guest' machines, both running Windows XP - one with Python and the other bits installed for doing the development and debugging work, the other set aside purely for testing the results of my work.
In the remainder of this document, where I talk about the development machine, I'll be referring to the PC where you do your coding and the building of your standalone application. If you see me talking about the testing machine, I'm referring to the machine that doesn't have Python, etc installed.
Tools Required - Software
In addition to the software you already have on your development machine, you will also need to install these packages:
- McMillan Installer (http://www.mcmillan-inc.com) - download this and install it under C:\Python23\Installer on your development machine.
- Inno Setup (http://www.jrsoftware.org/isinfo.php) - download and follow the prompts in the installation wizard
- Python for Windows Extensions (http://starship.python.net/crew/mhammond/) - as above
At the time of writing (March 18 2004) the McMillan website has been down for some time. It may or may not come back up again, in the meantime, you can download a copy of McMillan Installer version 5b5 from http://www.linux2000.com/downloads/installer_5b5_5.zip
Configuring McMillan Installer
Before you can do anything useful with the McMillan Installer, it needs to be configured. To do this, click Start --> run and type cmd to open a command line session on your development machine. Type the following commands:
cd C:\Python23\Installer
Configure.py
In the rest of this document, I'll be using my PIMP application as my example of building a standalone. The directory names will therefore reflect the way I personally like to work, your mileage may vary. Specifically, I have a directory C:\Python23\projects\pimp where I do all my coding, and everything else will be relative to this 'root' directory.
Generating A 'Spec' File For Your Application
The specification, or 'spec', file is the information used by McMillan Installer to compile and build the standalone version of your application. It's basically a list of the Python source files, Pythoncard resource files and any other stuff that your Pythoncard app needs in order to run properly. To generate the initial spec file, type these commands in a Command Prompt window:
cd C:\Python23\Installer
Makespec.py --icon ..\projects\pimp\pixmaps\pimp.ico
--out ..\projects\pimp ..\projects\pimp\pimp.py
You should replace pimp.py with the name of the Python script that corresponds to the main part of your application. The icon file isn't compulsory, but taking the time to select an icon makes your app look a little more polished.
You may find at this point that you wind up with an error message saying TypeError: unpack non-sequence. At the time of writing, the jury is still out on whether this is a bug in the Installer or in wxPython. The recommended solution is to comment out the call to RegistryImportDirector() on line 225 of the iu.py file in c:\python23\installer. Do the same on line 251 of the mf.py file and then re-run the Makespec.py command from above. This issue has been reported to Gordon as a bug, you can check the status of this item on the McMillan web site, the URL is http://mcmillan-inc.com/cgi-bin/BTSCGI.py/BTS/editbugs?bugid=73. Thanks to Brent Fentem <bfentem (at) sbcglobal.net> for the fix.
At this point, you'll have a basic spec file in your app's root directory, that probably looks something like this:
a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), '..\\projects\\pimp\\pimp.py'], pathex=['C:\\Python23\\Installer']) pyz = PYZ(a.pure) exe = EXE(pyz, a.scripts, exclude_binaries=1, name='buildpimp/pimp.exe', debug=0, strip=0, upx=0, console=1 , icon='..\\projects\\pimp\\pixmaps\\pimp.ico') coll = COLLECT( exe, a.binaries, strip=0, upx=0, name='distpimp')
The observant reader will have noticed (quite correctly) that this file seems to consist of Python source code! This helps us immensely in simplifying the file contents for ease of maintenance. Firstly add a line at the top of the file to define the root directory for your application, then modify the remainder of the spec file so it looks like this:
p = 'c:/python23/projects/pimp/' # defines project 'root' directory a = Analysis([os.path.join(HOMEPATH,'support\\_mountzlib.py'), os.path.join(HOMEPATH,'support\\useUnicode.py'), p + 'pimp.py'], pathex=['C:/Python23/Installer']) pyz = PYZ(a.pure) exe = EXE(pyz, a.scripts, exclude_binaries=1, name='buildpimp/pimp.exe', debug=0, strip=0, upx=0, console=1 , icon = p + 'pixmaps/pimp.ico') coll = COLLECT( exe, a.binaries + \ [('pimp.rsrc.py', p + 'pimp.rsrc.py', 'DATA')], strip=0, upx=0, name='distpimp')
Go back to your command prompt window, and issue this command:
Build.py ..\projects\pimp\pimp.spec
The build process should now run to completion with no fatal error messages. You will find 2 new folders have been created in your application root directory. buildpimp is used purely as a temporary work area when (re-)building the app. distpimp is the directory containing the standalone version of your program. It is the contents of this directory which need to be packaged up using Inno Setup and distributed, more on that part of the process later.
You should note the line in the spec file containing console=1. This causes your app to be run from a command-prompt style window, allowing you to see any unexpected error messages. When you're happy that the app builds and runs the way you want, you can change this to read console=0.
Resolving import errors
The Installer does its best to analyse your source code to see what modules you've used via Python import statements. For the most part, it does an excellent job, but it needs a little help where the Pythoncard part is concerned. Open a new Command Prompt window and type the following:
cd c:\python23\projects\pimp\distpimp
pimp
The program will now abort with an error message, complaining that it was unable to import some module or other. The precise one will depend on the Pythoncard components that your app uses, the first one mine complained about was statictext. This is where the first bit of tedious source code editing comes in. You need to explicitly import all of the Pythoncard components that your application uses. I did this the lazy way, by adding in each component in turn, rebuilding the standalone and re-running it, until I had no more import errors. The lines I ended up with at the top of my code looked like this:
# imports required by mcmillan installer
from PythonCard.components import statictext, imagebutton, textfield, \
textarea, list, staticbox, checkbox, passwordfield, radiogroup, spinner, \
combobox, choice, htmlwindow, bitmapcanvas
Finalizing the spec file
Having resolved all the issues with the components, you now need to add all the other parts of your application to the spec file, i.e. the Pythoncard resource files for any child windows, any images used for buttons, documentation files, etc.  The installer generated the standalone version of my app in the ./projects/distpimp on my machine. The folder name will be whatever you called your app with 'dist' on the front. I also found a ./projects/buildpimp directory had been created - according to the installers docs, this is used to store transient files during the build process and can be ignored.
Using Inno Setup
Inno Setup is a lovely piece of software that allows you to package up the contents of a directory into a single .EXE file that can easily be distributed. When someone downloads this and double-clicks, it launches the familiar series of dialogs through which a new program can be installed. It also takes care of adding an item in Control Panel --> Add and remove programs which allows your application to be removed just as easily.
Launch Inno Setup, and select the option to Create a new script file using the Script Wizard. Click OK, then Next to launch the wizard. I set the options on the application information section as follows:
- Application name: PIMP
- Application name including version:PIMP 0.7
- Appplication publisher: Phil Edwards
- Application website: http://www.linux2000.com
Click Next to get to the Application directory section. For most people, the defaults that Inno offers should be okay, but feel free to make amendments if required.
Click Next. You'll now see the Application files section. This is probably the most important part of the process, as this is where you tell Inno which specific files to include in the executable. Luckily, if you've done the part with McMillan Installer correctly, everything you need should already be there. Make sure you only include the files that your app really needs - for example, whilst putting this document together, I couldn't work out why PIMP kept having problems after I had installed it on the test machine. It took me a while to figure out that I'd included a pimp.ini file from my development machine in the SETUP.EXE produced by Inno. Taking this out cured the problem!
Click Next to get to the Application icons section. You should select whichever options you want the user to have.
Click Next. On the Application documentation section, I included a copy of the GPL in text format as the license file, and a copy of the PIMP changelog as the file to display before installation. This leads to the interesting situation of the end user having to agree to the terms of the GPL before being allowed to install the software! Irony is such a wonderful thing...
Click Next a couple more times and your SETUP.EXE file will be generated. Inno will put it in a ./Output directory off your main project root folder. You can now copy this file over to your test machine and check that it does actually install and run the way you expect it to.
The final task in this section is to ensure you save the Inno Setup script file that you just generated. For the record, my PIMP application generated the following:
; Script generated by the Inno Setup Script Wizard. ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! [Setup] AppName=PIMP AppVerName=PIMP 0.7 AppPublisher=Phil Edwards AppPublisherURL=http://www.linux2000.com/pimp.html AppSupportURL=http://www.linux2000.com/pimp.html AppUpdatesURL=http://www.linux2000.com/pimp.html DefaultDirName={pf}\PIMP DefaultGroupName=PIMP AllowNoIcons=yes LicenseFile=C:\Python23\projects\pimp\distpimp\doc\gpl.txt InfoBeforeFile=C:\Python23\projects\pimp\distpimp\changelog.txt [Tasks] ; NOTE: The following entry contains English phrases ("Create a desktop icon" ; and "Additional icons"). You are free to translate them into another language ; if required. Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:"; Flags: unchecked [Files] Source: "C:\Python23\projects\pimp\distpimp\pimp.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\_socket.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\_sre.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\_ssl.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\_winreg.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\advancedPrefsDialog.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\albumDialog.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\albumEdit.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\changelog.txt"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\editFilter.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\filterBatch.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\filterInfo.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\helpAbout.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\imageExportDialog.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\pandlDialog.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\passwdDialog.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\picPreview.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\pimp.exe"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\pimp.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\prefsDialog.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\pyexpat.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\python23.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\pywintypes23.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\readme.txt"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\slideShow.rsrc.py"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\win32api.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\wxmsw24h.dll"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\wxPython.helpc.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\wxPython.htmlc.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\wxPython.stc_c.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\wxPython.wxc.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\zlib.pyd"; DestDir: "{app}"; Flags: ignoreversion Source: "C:\Python23\projects\pimp\distpimp\doc\*"; DestDir: "{app}\doc"; Flags: ignoreversion recursesubdirs Source: "C:\Python23\projects\pimp\distpimp\pixmaps\*"; DestDir: "{app}\pixmaps"; Flags: ignoreversion recursesubdirs Source: "C:\Python23\projects\pimp\distpimp\themes\*"; DestDir: "{app}\themes"; Flags: ignoreversion recursesubdirs ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Icons] Name: "{group}\PIMP"; Filename: "{app}\pimp.exe" Name: "{userdesktop}\PIMP"; Filename: "{app}\pimp.exe"; Tasks: desktopicon
Preparing to distribute the finished app
We're almost ready to send the finished Windows version of PIMP out into the big bad world, but there are still a couple of sharp edges that need rubbing down.
Firstly, you will recall that when we built the standalone using McMillan Installer, we set the following options in the pimp.spec file:
exe = EXE(pyz, a.scripts, exclude_binaries=1, name='buildpimp/pimp.exe', debug=0, strip=0, upx=0, console=1 , icon = p + 'pixmaps/pimp.ico') ^^^^^^^^^
This causes the program to run in a command prompt style window, so we can see any run-time error messages produced. Obviously, the program will look pretty lame if we allow it to run this way on the end-users systems. You need to remember to change the console=1 to read console=0 before doing a final build of your program.
Secondly, the output executable will always be called SETUP.EXE, which i think is too generic. I prefer the file to include the name, version number and preferably the build number of the program in question. Open up the pimp.iss file that Inno saved and add the following line to the end of the [Setup] section:
OutputBaseFilename=pimp-0.7-1
There doesn't appear to be any way at present to force Inno to take this information from an external file, so you just have to remember to update it manually each time you release a new build of the program. Another job for the vapor-ware Pythoncard project manager, I think!
As a final check immediately before releasing a new version of PIMP, I try to remember to go also through the following checklist:
- Go through all of the .rsrc.py files and reset the position parameter to '-1, -1' - the Pythoncard resource editor will almost always set this to wherever the panel happened to be on our screen when you saved it, which isn't always what you want.
- If (like me!) you like to show off with screen shots of your app, ensure that the ones on your web site reflect the latest version.
- Check that the version and build numbers are correct in the various files.
- If you distribute a changelog and/or READMEfile with your app, check that you've updated it so that the release date is correct and it's up to date with the latest changes.
Vaporware alert! PythonCard project manager
In the process of preparing these notes, it's become painfully obvious to me that there's a need for a project manager of some sort to assist with the whole process of managing a PythonCard project from initial coding all the way through to the finished Inno-based installer binary. I've made a start on coding this, see the screenshot below for what the user interface will (maybe) look like:
I'm grateful for the code that Lawrie Abott originally wrote, which has proven to be the inspiration for this project. It's probably about time I left PIMP alone to fester for a bit, anyway. :-)
Page last updated: March 3rd 2004 03:00 UTC
That's all for today, folks!
$Revision: 1.5 $ : $Author: kasplat $ : Last updated $Date: 2004/07/26 15:35:32 $


Try out our Premium Member services: Virtual Legal Assistant, Query Alert Service and an ad-free experience. Free for one month and pay only if you like it.
IN THE COURT OF SH. DEVENDER KUMAR, CCJ-CUM-ARC (WEST), TIS HAZARI COURTS, DELHI. U-12/09/05 Sh. R. David S/o Sh. H. David R/o 31/7, West Patel Nagar, New Delhi Partner of M/s. David Paint Industries At C/157, Maya Puri Industrial Area, Phase II, New Delhi .......Petitioner Vs. Harbans Singh C/o Anand Sons Trade Linkers At C/157, Maya Puri Industrial Area, Phase II, New Delhi 110 014 .....Respondent
Date of institution : 12.07.2002 Date on which reserved for judgment : 22.05.2012 Date of decision : 22.05.2012 Judgement
Vide this Judgment, I shall dispose off a petition under Section 45 of Delhi Rent Control Act filed by the petitioner against the respondent. Brief facts of the case as under :
1. The petitioner has alleged that the firm of the petitioner namely M/s. David Paint Industries is tenant under the respondent in respect of one hall situated at ground floor of the factory premises bearing no. C/157, Maya Puri Industrial Area, Phase-II, New Delhi -110 014, on the monthly rent of Rs. 2,500/- per month. It is further alleged that it was agreed by the respondent to supply the electricity and electricity charges were payable as per consumption of the meter at the exorbitant rate of Rs. 6 per unit and these charges are being charged by the respondent in addition to misuse U12/09/05 R. David Vs. Harbans Singh 1/5 charges levied by Delhi Vidut Board. It is further alleged that the respondent is doing the trade of the electricity supply at exorbitant rate from the tenant just to black mail them. It is further alleged that the petitioner has already paid a sum of Rs. 1,00,000/- as security amount to the respondent. It is further alleged in the month of June 2001, the respondent refused to receive the rent and demanded a rent of Rs. 10,000/- and the petitioner had to issue a cheque for Rs. 10,000/-, but the same was dishonored, however the rent was paid in cash later on. It is further alleged that the petitioner has been paying rent regularly. It is further alleged that the month of February 2002, the respondent forced the petitioner to enhance the rent to Rs. 3,500/- per month and in order to increase the rent. Further the respondent has disconnected the electricity supply of the petitioner through sub-meter on 01.04.2002 without any reason and just cause. It is further alleged that the petitioner got served a legal notice dated 02.05.2002 upon the respondent to restore the electricity supply, but the respondent refused to reconnect the electricity and the petitioner is also regularly suffering damages, due to non- supply of electricity. It is prayed that the respondent be directed to restore the electricity supply or in alternative, DVB be directed to provide independent electricity connection to the petitioner.
2. The respondent has filed written statement thereby alleging that there is no relationship of landlord and tenant between the parties and M/s. David Paint Industries is a licensee under M/s. Anand Sons Trade Linkers i.e. a partnership firm. It is further alleged that the petition is bad for non- joinder of necessary parties as the partnership firm has not been impleaded in this case and petition of the petitioner is liable to be dismissed. It is further alleged that the petitioner was running a pollution unit which has been shut down by the Government. It is further alleged that the license fee of the premises was Rs. 13,000/- per month and the respondent was maintaining an account of the petitioner's firm and petitioner in arrears of license fee since February 2002. It is further alleged that the respondent had been making the payment of the electricity charges as per consumption of sub-meter, but it is denied that he has paid any advance of Rs. 1,00,000/-. It U12/09/05 R. David Vs. Harbans Singh 2/5 is denied that the petitioner is tenant for monthly rent of Rs. 2500/- or Rs. 3,500/- per month. It is further denied that the respondent is trying to enhance the rent of the premises or the electricity has been disconnected in order to get vacated the premises. It is further alleged that the Government of India has served a legal notice dated 26.4.2002 under Section 31 (a) of Air (Prevention and Control of Pollution) Act, 1981 and thereafter the petitioner has discontinued the manufacturing activities in the premises and stopped electricity consumption. The respondent has denied all the allegations of the petitioner and has prayed that this petition is liable to be dismissed.
3. The petitioner has filed replication to the written Statement and has denied the allegations of the petitioner that there is no relationship of landlord and tenant between the parties. It is further alleged that agreement dated 01.05.1996 is a forged document. Petitioner has denied all the allegations of the respondent and reaffirmed his pleadings.
4. To prove the case, the petitioner has examined himself as PW-1 and closed PE. The respondent has tendered her affidavit in examination in chief, but failed to appear before the court despite many opportunities for cross examination, due to examination in chief of RW-1 was also dispensed with on 11.01.2000. As such the respondent has not examined any witness and RE was closed on 11.01.2010.
5. I have heard the arguments and perused the record. Present petition under Section 45 of Delhi Rent Control Act has been filed by the petitioner in the capacity of partner of M/s. Davit Paint Industries. It is admitted fact that M/s. Davit Paint Industries is the partnership firm and a partnership firm may represent itself before the court through partners. A petition may be filed on behalf of partnership firm by the partners in the capacity partners of the firm but a partnership firm cannot be represented by a sole partner in the absence of other partners as well as firm. It is not a disputed fact that the partnership firm is still in existence and PW-1 has U12/09/05 R. David Vs. Harbans Singh 3/5 admitted that the partnership firm has not been dissolved. If the partnership is in existence then this petition should have been filed by firm through partners. A partnership firm may not be represented by a single partner, due to a single partner has no locus standi to represent firm. In a rent petition, relationship of landlord and tenant is very necessary and PW-1 has admitted that the premises is in occupation of the partnership firm. If the partnership firm is a tenant and has a separate entity then a petition filed by one partner is not maintainable.
6. Further, it is defence of the respondent that the petitioner or his firm is not the tenant in the tenanted premises and firm was only licensee. The license agreements dated 01.05.1996 and 01.04.1999 have been placed on record. Though these documents have not been proved by the respondent in the absence of examination of any witness, yet these documents were put to the PW-1 his during cross examination, PW-1 has admitted that the license agreements are bearing his the signature or signature of his brother. Even a letter Ex. PW1/R1 has been admitted by PW-1 in which a payment of license fee has been shown. As per these documents, it is clear that in the license fee was being paid by the petitioner and not the rent. Further, it has been admitted by PW-1 that the licence agreement dated 01.04.1999 is bearing his signature. It is further deposed that he has not taken any legal steps against the respondent for declaring the license agreement invalid. By admission of the petitioner, it is clear on record that the petitioner was not a tenant in the tenanted premises. As per content of agreement dated 01.05.1996, it was never intended by the parties to create a tenancy in respect of the tenanted premises and a specific and separate condition has been inserted in the license agreement that the license was not intended to create a tenancy. If it was not the interest of the parties to create a tenancy, a tenancy right in the tenanted premises is out of question. As such the petitioner is not the tenant in the tenanted premises.
7. Besides it, it is revealed by the license agreement that the U12/09/05 R. David Vs. Harbans Singh 4/5 respondent entered into license agreement on behalf of one M/s. Anand Sons Trade Linkers which is a partnership firm and by executing this licence deed by the respondent on behalf of partnership firm does not make the respondent responsible in his personal capacity. In fact, partnership firm M/s. Anand Sons Trade Linkers was a necessary party in this case, it has not been impleaded, accordingly this petition is also bad for non-joinder and mis-joinder of necessary parties. As such the petition of the petitioner is not maintainable on the legal ground, hence dismissed. File be consigned to record room after due compliance.
Dated:- 22.05.2012 (Devender Kumar) Announced in the open Court. CCJ-cum-ARC (West) Tis Hazari Courts, Delhi. U12/09/05 R. David Vs. Harbans Singh 5/5


{% extends 'email-layout.server.view.html' %} {% block content %}
Dear {{name}},
This is a confirmation that the password for your account has just been changed


RON97 up 13 sen, RON95 and diesel unchanged
KUALA LUMPUR, Nov 15 — The retail price of RON97 petrol will go up by 13 sen to RM2.70 sen a litre for the fuel price week November 16-22.
In a statement today, the Ministry of Finance said the retail prices of RON95 and diesel, however, will remain the same at RM2.08/litre and RM2.18/litre respectively.
Based on the calculations under the Automatic Pricing Mechanism (APM), the retail prices of RON95 and diesel for that period should be RM2.26/litre and RM2.31/litre respectively, it said.
“However, the retail prices for both fuels are maintained at RM2.08/litre and RM2.18/ litre in line with the government’s decision to stabilise petrol prices for petroleum products and reduce the cost of living,” it added.
The statement said the cost incurred by the government to provide the subsidies for the fuel price week (November 16 to 22) amounted to RM120.58 million. — Bernama


This example loads a data file. Chrome browser, and maybe others, won't allow this for local resources (file://). Use a local webserver or a different browser. e.g. Mozilla Firefox.


Caleb’s crossing by Geraldine Brooks
Martha’s Vineyard, 1650s: Bethia Mayfield is a young girl growing up in the tiny settlement of Great Harbor, amid a small band of pioneers and Puritans. Restless, bright and curious, but denied the education that her brothers receive, she slips away as often as she can to explore the island’s wild landscapes and observe its native Wampanoag inhabitants. At the age of twelve, she encounters Caleb, the young son of a chieftain, and the children form a secret friendship that gradually draws each into the alien world of the other.
The death of the heart by Elizabeth Bowen
Set amongst London’s fashionable high society in the late 1930’s, Bowen’s admired novel is a haunting depiction of innocence lost and a subtle blend of comedy and tragedy.
The Rosie project by Graeme Simsion
Meet Don Tillman. Don is getting married. He just doesn’t know who to yet. But he has designed a very detailed questionnaire to help him find the perfect woman. One thing he already knows, though, is that it’s not Rosie. Absolutely, completely, definitely not.
Stoner by John Williams
The son of a midwestern farmer, William Stoner comes to the University of Missouri in 1910 to study agriculture. Stoner tells of love and conflict, passion and responsibility against the backdrop of academic life in the early 20th century.
The secret history by Donna Tartt
Under the influence of their charismatic classics professor, a group of clever, eccentric misfits at an elite New England college discover a way of thinking and living that is a world away from the humdrum existence of their contemporaries. But when they go beyond the boundaries of normal morality their lives are changed profoundly and for ever.
Wonder by R J Palacio
Born with a terrible facial abnormality, Auggie has been home-schooled by his parents his whole life. Now, for the first time, he’s being sent to a real school – and he’s dreading it. All he wants is to be accepted – but can he convince his new classmates that he’s just like them, underneath it all?
The light between oceans by M L Stedman
A boat washes up on the shore of a remote lighthouse keeper’s island. It holds a dead man and a crying baby. The two islanders, Tom and his wife Izzy are about to make a devastating decision.
The interestings by Meg Wolitzer
On a warm July night in 1974, six teenagers play at being cool. The friendships they make this summer will be the most important of their lives. But decades later not everyone can sustain in adulthood what had seemed so special in adolescence. As their fortunes tilt precipitously over the years, some of them dealing with great struggle, others enjoying wealth and success, friendships are put under the strain of envy and crushing disappointment against the backdrop of a changing America.
The Burgess boys by Elizabeth Strout
Haunted by the freak accident that killed their father when they were children, Jim and Bob Burgess escaped from their hometown for New York City as soon as they possibly could. Jim, a sleek, successful corporate lawyer, has belittled his bighearted brother their whole lives, and Bob, a legal aid attorney who idolises Jim, has always taken it in his stride. But their long-standing dynamic is upended when their sister, Susan – the sibling who stayed behind – urgently calls them home.
Defending Jacob by William Landay
When a boy is discovered dead in the woods, a wave of shock ripples through the community of Newton, outside of Boston. Assistant DA Andy Barber is used to dealing with murder, but when evidence emerges that ties his son Jacob to the crime, Andy faces a very different challenge: preventing his son from being convicted of murder.
The art of falling by Kathryn Craft
Penelope Sparrow, a 28-year-old dancer, has spent her entire life focusing on the perfection of her body. But when she wakes up in a Philadelphia hospital unable to move after a near-fatal accident, she can’t remember the events leading up to her crushing 14-story fall. Now, with a second chance at life, Penny must find a way to reconnect with her past and come to terms with the limitations of her body.
Ammonites and leaping fish: a life in time by Penelope Lively
Taking in old age, the context of one’s life and times, memory, reading and writing, and the identifying cargo of possessions – two ammonites, a cat, a pair of American ducks and a leaping fish sherd, amongst others – this is an elegant, moving and deeply enjoyable memoir by one of our most loved writers.
The round house by Louise Erdrich
One Sunday in the spring of 1988, wife and mother Geraldine Coutts is brutally attacked on her North Dakota reservation. Traumatised and afraid in the aftermath, she shuts herself in her bedroom, and shuts everyone out, including her 13-year-old son Joe. While Geraldine’s husband, a tribal judge, endeavours to wrest justice from a situation that defies his keenest efforts, Joe becomes frustrated with his father’s official investigation and sets out with his best friends Cappy, Zack and Angus, to seek answers of his own.
The shadow of the wind by Carlos Ruiz Zafon
Hidden in the heart of the old city of Barcelona is a labyrinthine library of obscure & forgotten titles that have long gone out of print. A man brings his 10-year-old son to the library & allows him to choose one book to keep. But as he grows up, several people seem inordinately interested in his find.


core
/
com.mo.stratego.model.component
/
SoundComponent
/
<init>
<init>
SoundComponent
(
soundType
:
SoundType
)
Component that defines which sound should be played.


@*
* Copyright 2023 HM Revenue & Customs
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*@
@import config.TrackingConsentConfig
@()(implicit request: Request[_], flash: Flash, user: Option[CachedData], feedbackUrl: String, trackingConsentConfig: TrackingConsentConfig, messages: Messages)
@main_template(title = "Terms and conditions") {
Terms and conditions
This service is run by Civil Service Human Resources (CSHR). We'll handle the information you give to us in accordance with the General Data Protection Regulation Act. Our privacy and cookies statements explains how we will use your information.
In accepting these terms and conditions you're agreeing for us to contact you in regards to your application.
Responsibility for the service
Our aim is to make sure this service is constantly available, free from viruses and that the information we give is accurate and complete.
CSHR doesn't accept liability for:
- you being unable to access the service (eg because of excessive demand or because we've taken the service down for maintenance)
- delay or failure in receiving data
- indirect damages arising from you using the service or relying on its content
- the content and availability of external websites that link to the service or which are linked from it
What happens if you misuse your account
We may delete your account if you:
- use an inappropriate email address for your username
- submit an application posing as someone else
- create duplicate accounts
If you make a false declaration of disability any offer of employment will be withdrawn. You may not be able to apply again in the future.
Fast Stream Assessments
Terms of Use, Confidentiality, Disclaimer, Copyright and General
The conditions set out below pertain to the following assessments:
- FS Work Style Questionnaire Part 1
- FS Work Style Questionnaire Part 2
- FS Situational Judgement Questionnaire - Interpersonal Skills
- Numerical Test
- FS Learning Assessment
- FS Case Study Assessment
- Fast Stream Assessment Centre
Failure to comply with these Terms and Conditions may result in disqualification, so it is important that you read through them in detail and understand them before starting your assessment. By clicking the 'I Agree' button, you accept and agree to the following:
Terms of Use
By taking the assessments, you confirm that you are the named user for the account which is logged into the assessments. You are required to complete the assessments on your own without seeking assistance or support from any other person or source. Failure to comply may result in your application being withdrawn.
Confidentiality
All content provided to you during the assessments is the Crown’s confidential information and you are prohibited from making copies of any content provided to you and you may not disclose the content to any other person. Failure to comply may result in your application being withdrawn.
Disclaimer
In no event will the Crown be liable for any loss or damage to you or any other party that may arise from use of the content (other than those liabilities that cannot be excluded by law) including:
- any direct, indirect or consequential losses;
- any loss or damage caused by any causes of action whether based on contract, warranty, tort or any other legal theories;
- the use of the online assessment portal; and
- the inability to use the online assessment portal.
This applies if the loss or damage was foreseeable, arose in the normal course of events or you advised us that it might happen, including (but not limited to) the loss of income or revenue; salary; benefits or other payments; business; profits or contracts; opportunity; anticipated savings; data; goodwill or reputation; tangible property; and intangible property (including loss, corruption or damage to data or any computer system).
Copyright Notice
All content in this online assessment is owned by the Crown and subject to © Crown Copyright 2020. All rights are reserved and any unauthorised re-use, transmission, broadcast, public performance, distribution, copying, re-recording or other non-permitted use of the content will constitute an infringement of copyright. You are authorised to use the content for the purposes of the undertaking the following assessments only:
- FS Work Style Questionnaire Part 1
- FS Work Style Questionnaire Part 2
- FS Situational Judgement Questionnaire - Interpersonal Skills
- Numerical Test
- FS Learning Assessment
- FS Case Study Assessment
- Fast Stream Assessment Centre
If any content is not subject to Crown Copyright protection and/or belongs to a third party we’ll usually credit the author or copyright holder within the content itself.
The copyright in all your answers to the assessments shall be assigned on creation to the Crown. Candidate answers are exempt from the Data Protection Act 2018 under Paragraph 25 of Part 4 to Schedule 2 of that Act.
The Fast Stream assessment content is not available under the Open Government License v3.0
General
These Terms and Conditions are governed by and construed in accordance with the laws of England and Wales.
Any dispute you have which relates to these Terms and Conditions, or your use of the assessment portals (whether it be contractual or non-contractual), will be subject to the exclusive jurisdiction of the courts of England and Wales.
We’re not liable if we fail to comply with these Terms and Conditions because of circumstances beyond our reasonable control.
We might decide not to exercise or enforce any right available to us under these Terms and Conditions. We can always decide to exercise or enforce that right at a later date.
Doing this once will not mean we automatically waive the right on any other occasion.
If any of these Terms and Conditions are held to be invalid, unenforceable or illegal for any reason, the remaining Terms and Conditions will still apply.
Privacy Policy
The CSHR Privacy Notice (opens in new tab) sets out how we use your personal data, and your rights in relation to the assessments. It is made under Articles 13 and/or 14 of the General Data Protection Regulation (GDPR).
}


Project Dependencies
test
The following is a list of test dependencies for this project. These dependencies are only required to compile and run unit tests for the application:
| GroupId | ArtifactId | Version | Type | Licenses |
|---|---|---|---|---|
| junit | junit | 4.12 | jar | Eclipse Public License 1.0 |
| org.springframework | spring-core | 4.3.6.RELEASE | jar | The Apache Software License, Version 2.0 |
| org.springframework | spring-test | 4.3.6.RELEASE | jar | The Apache Software License, Version 2.0 |
provided
The following is a list of provided dependencies for this project. These dependencies are required to compile the application, but should be provided by default when using the library:
| GroupId | ArtifactId | Version | Type | Licenses |
|---|---|---|---|---|
| org.apache.tomcat | tomcat-servlet-api | 8.5.11 | jar | http://www.apache.org/licenses/LICENSE-2.0.txt and http://www.opensource.org/licenses/cddl1.txt |
Project Transitive Dependencies
The following is a list of transitive dependencies for this project. Transitive dependencies are the dependencies of the project dependencies.
test
The following is a list of test dependencies for this project. These dependencies are only required to compile and run unit tests for the application:
| GroupId | ArtifactId | Version | Type | Licenses |
|---|---|---|---|---|
| org.hamcrest | hamcrest-core | 1.3 | jar | New BSD License |
Project Dependency Graph
Dependency Tree
- org.apache.openmeetings:openmeetings-flash:jar:3.2.1
Openmeetings Flash Description: Module for OpenMeetings OpenLaszlo/Flex client
URL: http://openmeetings.apache.org/openmeetings-flash
Project Licenses: The Apache Software License, Version 2.0
- junit:junit:jar:4.12 (test)
JUnit Description: JUnit is a unit testing framework for Java, created by Erich Gamma and Kent Beck.
URL: http://junit.org
Project Licenses: Eclipse Public License 1.0
- org.hamcrest:hamcrest-core:jar:1.3 (test)
Hamcrest Core Description: This is the core API of hamcrest matcher framework to be used by third-party framework providers. This includes the a foundation set of matcher implementations for common operations.
URL: https://github.com/hamcrest/JavaHamcrest/hamcrest-core
Project Licenses: New BSD License
- org.hamcrest:hamcrest-core:jar:1.3 (test)
- org.springframework:spring-core:jar:4.3.6.RELEASE (test)
Spring Core Description: Spring Core
URL: https://github.com/spring-projects/spring-framework
Project Licenses: The Apache Software License, Version 2.0
- org.springframework:spring-test:jar:4.3.6.RELEASE (test)
Spring TestContext Framework Description: Spring TestContext Framework
URL: https://github.com/spring-projects/spring-framework
Project Licenses: The Apache Software License, Version 2.0
- org.apache.tomcat:tomcat-servlet-api:jar:8.5.11 (provided)
tomcat-servlet-api Description: javax.servlet package
URL: http://tomcat.apache.org/
Project Licenses: Apache License, Version 2.0 and Common Development And Distribution License (CDDL) Version 1.0
- junit:junit:jar:4.12 (test)
Licenses
Apache License, Version 2.0 and Common Development And Distribution License (CDDL) Version 1.0: tomcat-servlet-api
Eclipse Public License 1.0: JUnit
New BSD License: Hamcrest Core
The Apache Software License, Version 2.0: Openmeetings Flash, Spring Core, Spring TestContext Framework
Dependency File Details
| Total | Size | Entries | Classes | Packages | Java Version | Debug Information |
|---|---|---|---|---|---|---|
| Filename | Size | Entries | Classes | Packages | Java Version | Debug Information |
| junit-4.12.jar | 314.9 kB | 323 | 286 | 30 | 1.5 | Yes |
| tomcat-servlet-api-8.5.11.jar | 243.7 kB | 127 | 82 | 4 | 1.7 | Yes |
| hamcrest-core-1.3.jar | 45 kB | 52 | 45 | 3 | 1.5 | Yes |
| spring-core-4.3.6.RELEASE.jar | 1.1 MB | 838 | 790 | 41 | 1.6 | Yes |
| spring-test-4.3.6.RELEASE.jar | 598.8 kB | 483 | 443 | 31 | 1.6 | Yes |
| 5 | 2.3 MB | 1823 | 1646 | 109 | 1.7 | 5 |
| test: 4 | test: 2.1 MB | test: 1696 | test: 1564 | test: 105 | - | test: 4 |
| provided: 1 | provided: 243.7 kB | provided: 127 | provided: 82 | provided: 4 | - | provided: 1 |


Experience NY
Brooklyn Museum
General museum with collections ranging from ancient Egypt antiquities to Colonial American art
Addmission always free with the option to pay as you wish
Address: 200 Eastern Pkwy, Brooklyn, NY 11238
Find out MoreBrooklyn Botanic Garden
52-acre garden with over 14,000 plants and specality garderns
Addmission free on Saturday from 10 AM to 12 PM
Address: 990 Washington Ave, Brooklyn, NY 11225
Find out MoreMuseum of Modern Art (MoMA)
Museum that focuses on modern and contemporary art
Addmission free on Friday from 5:30 PM to 9 PM
Address: 11 W 53rd St, New York, NY 10019
Find out More9/11 Memorial Museum
Museum commemorating the 1993 bombing and September 11, 2001 attacks on World Trade Center
Addmission Free on Tuesday from 5 PM to 8 PM
Address: 180 Greenwich St, New York, NY 10007
Find out MoreQueen Museum of Arts
General art museum with documents and objects from 1939 and 1964 World’s Fairs
Addmission always free with the option to pay as you wish
Address: New York City Building, Meridian Rd, Queens, NY 11368
Find out MoreSocrates Sculpture Park
Outdoor sculpture and multi-media installations museum and public park
Addmission always free with the option to pay as you wish
Address: 32-01 Vernon Blvd, Queens, NY 11106
Find out MoreBronx Museum of Art
Museum that focuses on American contemporary and 20th-century works and includes art and design exhibitions from Latin America, Africa, and Asia
Addmission free on the first Friday of the month from 6 PM to 10 PM
Address: 1040 Grand Concourse, Bronx, NY 10456
Find out MoreNew York Botanical Garden
250-acre garden with over one million plants and several habitats
Addmission free On Wednesdays from 10 AM to 6 PM
Address: 2900 Southern Blvd, Bronx, NY 10458
Find out MoreStaten Island Museum
General interest museum with collections in Natural Sciences, Fine Art, and History Archives & Library
Addmission free on Tuesdays from 12 PM to 2 PM
Address: 1000 Richmond Terrace, Staten Island, NY 10301
Find out MoreNew York Chinese Scholar’s Garden
An authentic and traditional Chinese garden
Addmission free on the first Saturday of the month from 11 AM to 7 PM
Address: 1000 Richmond Terrace, Staten Island, NY 10301
Find out More


Calorie Information
| Calories | 249 |
| Total Fat | 12.8g |
| Cholesterol | 14.1mg |
| Sodium | 172.8mg |
| Carbohydrates | 33.8g |
| Sugar | 25.6g |
| Protein | 2.2g |
1, @Smiths Lorem ipsum dolor sit amet, consectetur adipisicing elit. Veniam illo consectetur numquam facilis architecto quis magni velit amet id harum sapiente unde aspernatur porro quam repudiandae tempora beatae, sit optio nulla tenetur! Earum pariatur, at quos assumenda magni voluptas corrupti repellat veniam tempora alias voluptate porro vero soluta iste. Quam!
4 days ago
2, @Smiths I recommend you to try it. It's a good cake with special taste. You will not regret about it. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Odio beatae culpa, eaque cum quisquam voluptates, ut dicta illum laboriosam, minus ea aut maxime quaerat saepe. Culpa adipisci a ipsam asperiores sint voluptatem eius illum id dicta vel, magni perspiciatis labore, quasi aperiam laudantium quod, dolor autem fuga ut vitae velit!
4 days ago
3, @Smiths I recommend you to try it. It's a good cake with special taste. You will not regret about it. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nam aliquid odit voluptate, ab illo itaque totam voluptas numquam sequi voluptates!
3 days ago
- Curly Whirly Mini Bake
Dark Chocolate, Flour, Salted Butter, Soft Brown Icing Sugar, Eggs, Baking Powder, Bicarbonate of Soda, Milk, Cocoa Powder, Cream Cheese, Vanilla Extract, Cream, Glucose, Food Colour. - Red Velvet Mini Bake
Icing Sugar, Caster Sugar, Cream Cheese, Mascarpone, Milk, Flour, Eggs, Cocoa Powder, Baking Powder, Glucose, Vanilla Extract, Sunflower Oil, Salt, Buttermilk, Red Wine Vinegar, Red Food Colouring. - Chocolate Raspberry Velvet Flour, Cocoa Powder, Baking Powder, Bicarbonate of Soda, Salt, Caster Sugar, Soy Milk, Sunflower Oil, Raspberry Jam, Vanilla Extract, Golden Syrup, Dark Chocolate, Raspberries, Lemon


I obtained my degree in Information Systems and Technology with a focus in Networking, however the courses I always found most engaging were in programming. After a networking internship and a tech support job, I moved into a support position in the software field.
Working for a software company reignited my drive to code. Over the last few years I have slowly begun to take on as many additional assignments and responsibilities outside of my support role as possible. I have also been committed to furthering my development knowledge outside of work with certifications, courses, and code camps.
I do a lot of coding in my free time for fun but when I am not coding I also enjoy audio recording, tabletop gaming, knitting, and spending time with my wife who also works in tech. We are expecting our first child at the end of the year and couldn't be more thrilled!
After five years working in technical support I am looking to advance my career in a direction that allows me to be more involved with code. I am currently seeking either a Junior Developer position or a more advanced support role with a focus in programming and potential to move on to a development role in the future.


Multiple Object Detection with TensorFlow
Wait for the model to load before trying the demo, it becomes visible upon success. (18MB~)
Webcam Object Detection and Classification
Enable Webcam


Add gene to the GO ribbon:
(can use gene symbol or model organism ID such as RGD:3889)
Clear GO ribbon


Westside Chinese School Registration
You can pay via VISA or Master Card. There will be three steps:
- Input your card information. If everything is correct, you will
see a green check.
- System will charge your card.
- System will show you whether the charge is successful or not.
Contacting bank, please wait ...


A link is specified using HTML tag .
This tag is called anchor tag and anything between the opening tag and the closing
tag becomes part of the link and a user can click that part to reach to the linked document.
The target Attribute
This attribute is used to specify the location where linked document is opened. Following
are possible options:
Use of Base Path
When you link HTML documents related to the same website, it is not required to give a
complete URL for every link.
Use
Linking to a Page Section
You can create a link to a particular section of a given webpage by using name attribute.
This is a two step process.
First create a link to the place where you want to reach with-in a webpage and name it
using HTML Text Links
Second step is to create a hyperlink to link the document and place where you want to
reach:
<a href="/html/html_text_links.htm#top">Go to the Top
This will produce following link, where you can click on the link generated Go to the Top
to reach to the top of the HTML Text Link .


Caution:
This page describes experimental features that are not yet available in a stable release. Don't rely on experimental builds of React in production apps. These features may change significantly and without a warning before they become a part of React.
This documentation is aimed at early adopters and people who are curious. If you're new to React, don't worry about these features – you don't need to learn them right now. For example, if you're looking for a data fetching tutorial that works today, read this article instead.
Usually, when we update the state, we expect to see changes on the screen immediately. This makes sense because we want to keep our app responsive to user input. However, there are cases where we might prefer to defer an update from appearing on the screen.
For example, if we switch from one page to another, and none of the code or data for the next screen has loaded yet, it might be frustrating to immediately see a blank page with a loading indicator. We might prefer to stay longer on the previous screen. Implementing this pattern has historically been difficult in React. Concurrent Mode offers a new set of tools to do that.
Let's revisit this demo from the previous page about Suspense for Data Fetching.
When we click the "Next" button to switch the active profile, the existing page data immediately disappears, and we see the loading indicator for the whole page again. We can call this an "undesirable" loading state. It would be nice if we could "skip" it and wait for some content to load before transitioning to the new screen.
React offers a new built-in useTransition()
Hook to help with this.
We can use it in three steps.
First, we'll make sure that we're actually using Concurrent Mode. We'll talk more about adopting Concurrent Mode later, but for now it's sufficient to
know that we need to use ReactDOM.createRoot()
rather than ReactDOM.render()
for this
feature to work:
const rootElement = document.getElementById("root");
// Opt into Concurrent Mode
ReactDOM.createRoot(rootElement).render(<App />);
Next, we'll add an import for the useTransition
Hook from React:
Finally, we'll use it inside the App
component:
function App() {
const [resource, setResource] = useState(initialResource);
const [startTransition, isPending] = useTransition({
timeoutMs: 3000
});
// ...
By itself, this code doesn't do anything yet. We will need to use this Hook's return values to set
up our state transition. There are two values returned from useTransition
:
startTransition
is a function. We'll use it to tell React which state update we want to defer.
isPending
is a boolean. It's React telling us whether that transition is ongoing at the moment.We will use them right below.
Note we passed a configuration object to useTransition
. Its timeoutMs
property specifies
how long we're willing to wait for the transition to finish. By passing {timeoutMs:
3000}
, we say "If the next profile takes more than 3 seconds to load, show the big spinner – but before
that timeout it's okay to keep showing the previous screen".
Our "Next" button click handler sets the state that switches the current profile in the state:
<button
onClick={() => {
const nextUserId = getNextId(resource.userId);
setResource(fetchProfileData(nextUserId));
}}
>
We'll wrap that state update into startTransition
. That's how we tell React we don't mind React
delaying that state update if it leads to an undesirable loading state:
<button
onClick={() => {
startTransition(() => {
const nextUserId = getNextId(resource.userId);
setResource(fetchProfileData(nextUserId));
});
}}
>
Press "Next" a few times. Notice it already feels very different. Instead of immediately seeing an empty screen on click, we now keep seeing the previous page for a while. When the data has loaded, React transitions us to the new screen.
If we make our API responses take 5 seconds, we can confirm that now React "gives up" and transitions anyway to the next screen after 3 seconds. This is because we passed {timeoutMs: 3000}
to useTransition()
. For example, if we passed {timeoutMs: 60000}
instead, it would wait a whole minute.
There's still something that feels broken about our last example. Sure, it's nice not to see a "bad" loading state. But having no indication of progress at all feels even worse! When we click "Next", nothing happens and it feels like the app is broken.
Our useTransition()
call returns two values: startTransition
and isPending
.
We've already used startTransition
to wrap the state update. Now we're going to use
isPending
too. React gives this boolean to us so we can tell whether we're currently waiting
for this transition to finish. We'll use it to indicate that something is happening:
return (
<>
<button
disabled={isPending}
onClick={() => {
startTransition(() => {
const nextUserId = getNextId(resource.userId);
setResource(fetchProfileData(nextUserId));
});
}}
>
Next
</button>
{isPending ? " Loading..." : null}
<ProfilePage resource={resource} />
</>
);
Now, this feels a lot better! When we click Next, it gets disabled because clicking it multiple times doesn't make sense. And the new "Loading…" tells the user that the app didn't freeze.
Let's take another look at all the changes we've made since the original example:
function App() {
const [resource, setResource] = useState(initialResource);
const [startTransition, isPending] = useTransition({
timeoutMs: 3000
});
return (
<>
<button
disabled={isPending}
onClick={() => {
startTransition(() => {
const nextUserId = getNextId(resource.userId);
setResource(fetchProfileData(nextUserId));
});
}}
>
Next
</button>
{isPending ? " Loading..." : null}
<ProfilePage resource={resource} />
</>
);
}
It took us only seven lines of code to add this transition:
useTransition
Hook and used it in the component that updates the state.{timeoutMs: 3000}
to stay on the previous screen for at most 3 seconds.startTransition
to tell React it's okay to delay it.isPending
to communicate the state transition progress to the user and to disable the
button.As a result, clicking "Next" doesn't perform an immediate state transition to an "undesirable" loading state, but instead stays on the previous screen and communicates progress there.
This wasn't very difficult to implement. However, if you start thinking about how this could possibly work, it might
become a little mindbending. If we set the state, how come we don't see the result right away? Where is the
next <ProfilePage>
rendering?
Clearly, both "versions" of <ProfilePage>
exist at the same time. We know the old one exists
because we see it on the screen and even display a progress indicator on it. And we know the new version also exists
somewhere, because it's the one that we're waiting for!
But how can two versions of the same component exist at the same time?
This gets at the root of what Concurrent Mode is. We've previously said it's a bit like React
working on state update on a "branch". Another way we can conceptualize is that wrapping a state update in
startTransition
begins rendering it "in a different universe", much like in science fiction
movies. We don't "see" that universe directly – but we can get a signal from it that tells us something is happening
(isPending
). When the update is ready, our "universes" merge back together, and we see the result on
the screen!
Play a bit more with the demo, and try to imagine it happening.
Of course, two versions of the tree rendering at the same time is an illusion, just like the idea that all programs run on your computer at the same time is an illusion. An operating system switches between different applications very fast. Similarly, React can switch between the version of the tree you see on the screen and the version that it's "preparing" to show next.
An API like useTransition
lets you focus on the desired user experience, and not think about the
mechanics of how it's implemented. Still, it can be a helpful metaphor to imagine that updates wrapped in
startTransition
happen "on a branch" or "in a different world".
As we learned from the Suspense walkthrough, any component can
"suspend" any time if some data it needs is not ready yet. We can strategically place <Suspense>
boundaries in different parts of the tree to handle this, but it won't always be enough.
Let's get back to our first Suspense demo where there was just one profile. Currently, it fetches the data only once. We'll add a "Refresh" button to check for server updates.
Our first attempt might look like this:
const initialResource = fetchUserAndPosts();
function ProfilePage() {
const [resource, setResource] = useState(initialResource);
function handleRefreshClick() {
setResource(fetchUserAndPosts());
}
return (
<Suspense fallback={
Loading profile...
}>
<ProfileDetails resource={resource} />
<button onClick={handleRefreshClick}>
Refresh
</button>
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
</Suspense>
);
}
In this example, we start data fetching at the load and every time you press "Refresh". We put the result of calling fetchUserAndPosts()
into state so that components below can start reading the new data from the request we just kicked off.
We can see in this example that pressing "Refresh" works.
The <ProfileDetails>
and <ProfileTimeline>
components receive a new
resource
prop that represents the fresh data, they "suspend" because we don't have a response yet, and
we see the fallbacks. When the response loads, we can see the updated posts (our fake API adds them every 3
seconds).
However, the experience feels really jarring. We were browsing a page, but it got replaced by a loading state right as we were interacting with it. It's disorienting. Just like before, to avoid showing an undesirable loading state, we can wrap the state update in a transition:
function ProfilePage() {
const [startTransition, isPending] = useTransition({
// Wait 10 seconds before fallback
timeoutMs: 10000
});
const [resource, setResource] = useState(initialResource);
function handleRefreshClick() {
startTransition(() => {
setResource(fetchProfileData());
});
}
return (
<Suspense fallback={
Loading profile...
}>
<ProfileDetails resource={resource} />
<button
onClick={handleRefreshClick}
disabled={isPending}
>
{isPending ? "Refreshing..." : "Refresh"}
</button>
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
</Suspense>
);
}
This feels a lot better! Clicking "Refresh" doesn't pull us away from the page we're browsing anymore. We see something is loading "inline", and when the data is ready, it's displayed.
We can now see that the need for useTransition
is very common. Pretty much any button click or interaction that can lead to a component suspending needs to be wrapped in useTransition
to avoid accidentally hiding something the user is interacting with.
This can lead to a lot of repetitive code across components. This is why we generally recommend to bake useTransition
into the design system components of your app. For example, we can extract the transition logic into our own <Button>
component:
function Button({ children, onClick }) {
const [startTransition, isPending] = useTransition({
timeoutMs: 10000
});
function handleClick() {
startTransition(() => {
onClick();
});
}
const spinner = (
// ...
);
return (
<>
<button
onClick={handleClick}
disabled={isPending}
>
{children}
</button>
{isPending ? spinner : null}
</>
);
}
Note that the button doesn't care what state we're updating. It's wrapping any state updates that
happen during its onClick
handler into a transition. Now that our <Button>
takes
care of setting up the transition, the <ProfilePage>
component doesn't need to set up its own:
function ProfilePage() {
const [resource, setResource] = useState(initialResource);
function handleRefreshClick() {
setResource(fetchProfileData());
}
return (
<Suspense fallback={
Loading profile...
}>
<ProfileDetails resource={resource} />
<Button onClick={handleRefreshClick}>
Refresh
</Button>
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
</Suspense>
);
}
When a button gets clicked, it starts a transition and calls props.onClick()
inside of it – which
triggers handleRefreshClick
in the <ProfilePage>
component. We start fetching the
fresh data, but it doesn't trigger a fallback because we're inside a transition, and the 10 second timeout specified
in the useTransition
call hasn't passed yet. While a transition is pending, the button displays an
inline loading indicator.
We can see now how Concurrent Mode helps us achieve a good user experience without sacrificing isolation and modularity of components. React coordinates the transition.
By now we have discussed all of the different visual states that an update may go through. In this section, we will give them names and talk about the progression between them.
At the very end, we have the Complete state. That's where we want to eventually get to. It represents the moment when the next screen is fully rendered and isn't loading more data.
But before our screen can be Complete, we might need to load some data or code. When we're on the next screen, but some parts of it are still loading, we call that a Skeleton state.
Finally, there are two primary ways that lead us to the Skeleton state. We will illustrate the difference between them with a concrete example.
Open this example and click "Open Profile". You will see several visual states one by one:

Loading the app...

fallback.<ProfilePage>
component with
Loading posts...

inside.<ProfilePage>
component with no fallbacks inside. Everything was fetched.How do we separate the Receded and the Skeleton states? The difference between them is that the Receded state feels like "taking a step back" to the user, while the Skeleton state feels like "taking a step forward" in our progress to show more content.
In this example, we started our journey on the <HomePage>
:
After the click, React started rendering the next screen:
<Suspense fallback={...}>
{/* next screen */}
<ProfilePage>
<ProfileDetails />
<Suspense fallback={...}>
<ProfileTimeline />
</Suspense>
</ProfilePage>
</Suspense>
Both <ProfileDetails>
and <ProfileTimeline>
need data to render, so they suspend:
<Suspense fallback={...}>
{/* next screen */}
<ProfilePage>
<ProfileDetails /> {/* suspends! */}
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline /> {/* suspends! */}
</Suspense>
</ProfilePage>
</Suspense>
When a component suspends, React needs to show the closest fallback. But the closest fallback to <ProfileDetails>
is at the top level:
<Suspense fallback={
// We see this fallback now because of <ProfileDetails>

Loading the app...

}>
{/* next screen */}
<ProfilePage>
<ProfileDetails /> {/* suspends! */}
<Suspense fallback={...}>
<ProfileTimeline />
</Suspense>
</ProfilePage>
</Suspense>
This is why when we click the button, it feels like we've "taken a step back". The <Suspense>
boundary which was previously showing useful content (<HomePage />
) had to "recede" to showing
the fallback (
Loading the app...

). We call that a Receded state.
As we load more data, React will retry rendering, and <ProfileDetails>
can render successfully.
Finally, we're in the Skeleton state. We see the new page with missing parts:
<Suspense fallback={...}>
{/* next screen */}
<ProfilePage>
<ProfileDetails />
<Suspense fallback={
// We see this fallback now because of <ProfileTimeline>

Loading posts...

}>
<ProfileTimeline /> {/* suspends! */}
</Suspense>
</ProfilePage>
</Suspense>
Eventually, they load too, and we get to the Complete state.
This scenario (Receded → Skeleton → Complete) is the default one. However, the Receded state is not very pleasant because it "hides" existing information. This is why React lets us opt into a different sequence (Pending → Skeleton → Complete) with useTransition
.
When we useTransition
, React will let us "stay" on the previous screen – and show a progress indicator there. We call that a Pending state. It feels much better than the Receded state because none of our existing content disappears, and the page stays interactive.
You can compare these two examples to feel the difference:
The only difference between these two examples is that the first uses regular <button>
s, but the second one uses our custom <Button>
component with useTransition
.
<Suspense>
Open this example. When you press a button, you'll see the Pending state for a second before moving on. This transition feels nice and fluid.
We will now add a brand new feature to the profile page – a list of fun facts about a person:
function ProfilePage({ resource }) {
return (
<>
<ProfileDetails resource={resource} />
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
<ProfileTrivia resource={resource} />
</>
);
}
function ProfileTrivia({ resource }) {
const trivia = resource.trivia.read();
return (
<>

Fun Facts

{trivia.map(fact => (

{fact.text}

))}

</>
);
}
If you press "Open Profile" now, you can tell something is wrong. It takes a whole seven seconds to make the transition now! This is because our trivia API is too slow. Let's say we can't make the API faster. How can we improve the user experience with this constraint?
If we don't want to stay in the Pending state for too long, our first instinct might be to set timeoutMs
in useTransition
to something smaller, like 3000
. You can try this here. This lets us escape the prolonged Pending
state, but we still don't have anything useful to show!
There is a simpler way to solve this. Instead of making the transition shorter, we can "disconnect" the slow component from the transition by wrapping it into <Suspense>
:
function ProfilePage({ resource }) {
return (
<>
<ProfileDetails resource={resource} />
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
<Suspense fallback={
Loading fun facts...
}>
<ProfileTrivia resource={resource} />
</Suspense>
</>
);
}
This reveals an important insight. React always prefers to go to the Skeleton state as soon as possible. Even if we use transitions with long timeouts everywhere, React will not stay in the Pending state for longer than necessary to avoid the Receded state.
If some feature isn't a vital part of the next screen, wrap it in <Suspense>
and let it
load lazily. This ensures we can show the rest of the content as soon as possible. Conversely, if a
screen is not worth showing without some component, such as <ProfileDetails>
in our
example, do not wrap it in <Suspense>
. Then the transitions will "wait" for it to be
ready.
When we're already on the next screen, sometimes the data needed to "unlock" different <Suspense>
boundaries arrives in quick succession. For example, two different responses might arrive after 1000ms and 1050ms,
respectively. If you've already waited for a second, waiting another 50ms is not going to be perceptible. This is
why React reveals <Suspense>
boundaries on a schedule, like a "train" that arrives periodically.
This trades a small delay for reducing the layout thrashing and the number of visual changes presented to the user.
You can see a demo of this here. The "posts" and "fun facts" responses come within 100ms of each other. But React coalesces them and "reveals" their Suspense boundaries together.
Our Button
component will immediately show the Pending state indicator on click:
function Button({ children, onClick }) {
const [startTransition, isPending] = useTransition({
timeoutMs: 10000
});
// ...
return (
<>
<button onClick={handleClick} disabled={isPending}>
{children}
</button>
{isPending ? spinner : null}
</>
);
}
This signals to the user that some work is happening. However, if the transition is relatively short (less than 500ms), it might be too distracting and make the transition itself feel slower.
One possible solution to this is to delay the spinner itself from displaying:
.DelayedSpinner {
animation: 0s linear 0.5s forwards makeVisible;
visibility: hidden;
}
@keyframes makeVisible {
to {
visibility: visible;
}
}
const spinner = (

{/* ... */}

);
return (
<>
<button onClick={handleClick}>{children}</button>
{isPending ? spinner : null}
</>
);
With this change, even though we're in the Pending state, we don't display any indication to the user until 500ms has passed. This may not seem like much of an improvement when the API responses are slow. But compare how it feels before and after when the API call is fast. Even though the rest of the code hasn't changed, suppressing a "too fast" loading state improves the perceived performance by not calling attention to the delay.
The most important things we learned so far are:
useTransition
, we can opt into showing a Pending state first instead. This will keep us on the previous screen while the next screen is being prepared.<Suspense>
boundary.useTransition
in every other component, we can build it into our design system.Transitions are probably the most common Concurrent Mode pattern you'll encounter, but there are a few more patterns you might find useful.
When you design React components, it is usually best to find the "minimal representation" of state. For example,
instead of keeping firstName
, lastName
, and fullName
in state, it's usually
better keep only firstName
and lastName
, and then calculate fullName
during
rendering. This lets us avoid mistakes where we update one state but forget the other state.
However, in Concurrent Mode there are cases where you might want to "duplicate" some data in different state variables. Consider this tiny translation app:
const initialQuery = "Hello, world";
const initialResource = fetchTranslation(initialQuery);
function App() {
const [query, setQuery] = useState(initialQuery);
const [resource, setResource] = useState(initialResource);
function handleChange(e) {
const value = e.target.value;
setQuery(value);
setResource(fetchTranslation(value));
}
return (
<>
<input
value={query}
onChange={handleChange}
/>
<Suspense fallback={
Loading...
}>
<Translation resource={resource} />
</Suspense>
</>
);
}
function Translation({ resource }) {
return (

{resource.read()}

);
}
Notice how when you type into the input, the <Translation>
component suspends, and we see the

Loading...

fallback until we get fresh results. This is not ideal. It would be
better if we could see the previous translation for a bit while we're fetching the next one.
In fact, if we open the console, we'll see a warning:
Warning: App triggered a user-blocking update that suspended.
The fix is to split the update into multiple parts: a user-blocking update to provide immediate feedback, and another update that triggers the bulk of the changes.
Refer to the documentation for useTransition to learn how to implement this pattern.
As we mentioned earlier, if some state update causes a component to suspend, that state update should be wrapped in a
transition. Let's add useTransition
to our component:
function App() {
const [query, setQuery] = useState(initialQuery);
const [resource, setResource] = useState(initialResource);
const [startTransition, isPending] = useTransition({
timeoutMs: 5000
});
function handleChange(e) {
const value = e.target.value;
startTransition(() => {
setQuery(value);
setResource(fetchTranslation(value));
});
}
// ...
}
Try typing into the input now. Something's wrong! The input is updating very slowly.
We've fixed the first problem (suspending outside of a transition). But now because of the transition, our state doesn't update immediately, and it can't "drive" a controlled input!
The answer to this problem is to split the state in two parts: a "high priority" part that updates immediately, and a "low priority" part that may wait for a transition.
In our example, we already have two state variables. The input text is in query
, and we read the translation from resource
. We want changes to the query
state to happen immediately, but changes to the resource
(i.e. fetching a new translation) should trigger a transition.
So the correct fix is to put setQuery
(which doesn't suspend) outside the transition, but
setResource
(which will suspend) inside of it.
function handleChange(e) {
const value = e.target.value;
// Outside the transition (urgent)
setQuery(value);
startTransition(() => {
// Inside the transition (may be delayed)
setResource(fetchTranslation(value));
});
}
With this change, it works as expected. We can type into the input immediately, and the translation later "catches up" to what we have typed.
By default, React always renders a consistent UI. Consider code like this:
React guarantees that whenever we look at these components on the screen, they will reflect data from the same
user
. If a different user
is passed down because of a state update, you would see them
changing together. You can't ever record a screen and find a frame where they would show values from different
user
s. (If you ever run into a case like this, file a bug!)
This makes sense in the vast majority of situations. Inconsistent UI is confusing and can mislead users. (For example, it would be terrible if a messenger's Send button and the conversation picker pane "disagreed" about which thread is currently selected.)
However, sometimes it might be helpful to intentionally introduce an inconsistency. We could do it manually by "splitting" the state like above, but React also offers a built-in Hook for this:
import { useDeferredValue } from 'react';
const deferredValue = useDeferredValue(value, {
timeoutMs: 5000
});
To demonstrate this feature, we'll use the profile switcher example. Click the "Next" button and notice how it takes 1 second to do a transition.
Let's say that fetching the user details is very fast and only takes 300 milliseconds. Currently, we're waiting a whole second because we need both user details and posts to display a consistent profile page. But what if we want to show the details faster?
If we're willing to sacrifice consistency, we could pass potentially stale data to the components that delay
our transition. That's what useDeferredValue()
lets us do:
function ProfilePage({ resource }) {
const deferredResource = useDeferredValue(resource, {
timeoutMs: 1000
});
return (
<Suspense fallback={
Loading profile...
}>
<ProfileDetails resource={resource} />
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline
resource={deferredResource}
isStale={deferredResource !== resource}
/>
</Suspense>
</Suspense>
);
}
function ProfileTimeline({ isStale, resource }) {
const posts = resource.posts.read();
return (

{posts.map(post => (

{post.text}

))}

);
}
The tradeoff we're making here is that <ProfileTimeline>
will be inconsistent with other
components and potentially show an older item. Click "Next" a few times, and you'll notice it. But thanks to that,
we were able to cut down the transition time from 1000ms to 300ms.
Whether or not it's an appropriate tradeoff depends on the situation. But it's a handy tool, especially when the content doesn't change noticeably between items, and the user might not even realize they were looking at a stale version for a second.
It's worth noting that useDeferredValue
is not only useful for data fetching. It also helps
when an expensive component tree causes an interaction (e.g. typing in an input) to be sluggish. Just like we can
"defer" a value that takes too long to fetch (and show its old value despite other components updating), we can do
this with trees that take too long to render.
For example, consider a filterable list like this:
function App() {
const [text, setText] = useState("hello");
function handleChange(e) {
setText(e.target.value);
}
return (

Type into the input:{" "}
<input value={text} onChange={handleChange} />

...
<MySlowList text={text} />

);
}
In this example, every item in <MySlowList>
has an artificial slowdown – each of them
blocks the thread for a few milliseconds. We'd never do this in a real app, but this helps us simulate
what can happen in a deep component tree with no single obvious place to optimize.
We can see how typing in the input causes stutter. Now let's add useDeferredValue
:
function App() {
const [text, setText] = useState("hello");
const deferredText = useDeferredValue(text, {
timeoutMs: 5000
});
function handleChange(e) {
setText(e.target.value);
}
return (

Type into the input:{" "}
<input value={text} onChange={handleChange} />

...
<MySlowList text={deferredText} />

);
}
Now typing has a lot less stutter – although we pay for this by showing the results with a lag.
How is this different from debouncing? Our example has a fixed artificial delay (3ms for every one of 80 items), so
there is always a delay, no matter how fast our computer is. However, the useDeferredValue
value only
"lags behind" if the rendering takes a while. There is no minimal lag imposed by React. With a more realistic
workload, you can expect the lag to adjust to the user's device. On fast machines, the lag would be smaller or
non-existent, and on slow machines, it would be more noticeable. In both cases, the app would remain responsive.
That's the advantage of this mechanism over debouncing or throttling, which always impose a minimal delay and can't
avoid blocking the thread while rendering.
Even though there is an improvement in responsiveness, this example isn't as compelling yet because Concurrent Mode
is missing some crucial optimizations for this use case. Still, it is interesting to see that features like
useDeferredValue
(or useTransition
) are useful regardless of whether we're waiting for
network or for computational work to finish.
<SuspenseList>
is the last pattern that's related to orchestrating loading states.
Consider this example:
function ProfilePage({ resource }) {
return (
<>
<ProfileDetails resource={resource} />
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
<Suspense fallback={
Loading fun facts...
}>
<ProfileTrivia resource={resource} />
</Suspense>
</>
);
}
The API call duration in this example is randomized. If you keep refreshing it, you will notice that sometimes the posts arrive first, and sometimes the "fun facts" arrive first.
This presents a problem. If the response for fun facts arrives first, we'll see the fun facts below the

Loading posts...

fallback for posts. We might start reading them, but then the
posts response will come back, and shift all the facts down. This is jarring.
One way we could fix it is by putting them both in a single boundary:
<Suspense fallback={
Loading posts and fun facts...
}>
<ProfileTimeline resource={resource} />
<ProfileTrivia resource={resource} />
</Suspense>
The problem with this is that now we always wait for both of them to be fetched. However, if it's the posts that came back first, there's no reason to delay showing them. When fun facts load later, they won't shift the layout because they're already below the posts.
Other approaches to this, such as composing Promises in a special way, are increasingly difficult to pull off when the loading states are located in different components down the tree.
To solve this, we will import SuspenseList
:
<SuspenseList>
coordinates the "reveal order" of the closest <Suspense>
nodes below it:
function ProfilePage({ resource }) {
return (
<SuspenseList revealOrder="forwards">
<ProfileDetails resource={resource} />
<Suspense fallback={
Loading posts...
}>
<ProfileTimeline resource={resource} />
</Suspense>
<Suspense fallback={
Loading fun facts...
}>
<ProfileTrivia resource={resource} />
</Suspense>
</SuspenseList>
);
}
The revealOrder="forwards"
option means that the closest <Suspense>
nodes inside this list will only "reveal" their content in the order they appear in the tree – even if the data for them arrives in a different order. <SuspenseList>
has other interesting modes: try changing "forwards"
to "backwards"
or "together"
and see what happens.
You can control how many loading states are visible at once with the tail
prop. If we specify
tail="collapsed"
, we'll see at most one fallback at a time. You can play with it here.
Keep in mind that <SuspenseList>
is composable, like anything in React. For example, you can create a grid by putting several <SuspenseList>
rows inside a <SuspenseList>
table.
Concurrent Mode offers a powerful UI programming model and a set of new composable primitives to help you orchestrate delightful user experiences.
It's a result of several years of research and development, but it's not finished. In the section on adopting Concurrent Mode, we'll describe how you can try it and what you can expect.


--- layout: post title: energie in motion date: '2007-10-31T07:23:46+00:00' tags: [] tumblr_url: http://backlog.robbevan.com/post/17931704/energie-in-motion ---
Energie in Motion


If you have ever heard of Bitcoin, then most likely you have heard of Blockchain as well. Why? Because the latter is the technology at the very heart of virtual currencies, including Bitcoin, Litecoin and Ethereum.
Blockchain as a technology was first spoken about in 1991 by researchers Stuart Haber and W. Scott Stornetta. However, it was not until 2009 that it had its first application in the real world.
If you google the name, the search engine will give you a fair number of articles about the technology which is normally called a “ledger that can record transactions”. Such transactions are made in the most efficient way. But let us get to the core of the matter.
In simple words, the name of Blockchain speaks for itself. It is a technology that implies chaining the blocks together.
Each block encodes any transaction made by a party and can be uniquely identified. What is a transaction? A transaction is any exchange of value, for instance, a purchase of groceries, or a money transfer.
As the term suggests, each new block is connected to the previous one. The chain is irreversible, which means that nobody can delete a block from it or insert a block in between the existing blocks.
Four steps must be taken here:
Eventually every single block you have added becomes publicly available to view, so it is not anonymous. However, nobody can see the actual names of the participants, as the information about them is stored as a code. The fact that each computer in the network has a copy of each block makes it unbelievably hard for a hacker to manipulate information encoded in them.
On the other hand, how safe is it not to know who exactly is adding the blocks to the blockchain?
In Blockchain a linear, chronological sequence is used. Thus, it ensures that each new block with the data is added at the end of the chain. In Bitcoin, for instance, every block has a position which is identified as “height”. So, the newly added block would have the highest value in its position. This makes it hard to change the sequence of the blocks. Because the change in information leads to a different hash, the hacker would need to change the hash code in every single block that comes before that. How many years will it take a hacker to do it?
Blockchain simplifies the process of coordination and verification as there is always a single version of the records, or, in other words, a single database. To sum up, blockchain has plenty of benefits, such as security and quality assurance that make the technology quite appealing as an investment.
It has been estimated that in 2018 financial companies invested around $ 2.1 billion into the research of the new implications of Blockchain. Therefore, Blockchain is seen to have a potential to be used in many more ways than just financial transactions, but also decentralized applications, voting platforms and even server-free internet!