Document not found (404)
+This URL is invalid, sorry. Please use the navigation bar or search to continue.
+ +diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..f173110 --- /dev/null +++ b/.nojekyll @@ -0,0 +1 @@ +This file makes sure that Github Pages doesn't process mdBook's output. diff --git a/404.html b/404.html new file mode 100644 index 0000000..2b2729b --- /dev/null +++ b/404.html @@ -0,0 +1,190 @@ + + +
+ + +This URL is invalid, sorry. Please use the navigation bar or search to continue.
+ +Please submit bug reports, +feature requests, +or general feedback to our +Bug Tracker on GitHub.
+The easiest way to contribute to this project +is by clicking on the button in the top right corner of any page. +This will open the corresponding page on GitHub, +where you can add or modify content +and then commit the change.
+For more elaborate changes please:
+Special thanks to Kevin Amado1 for writing these docs.
+VP Development 2022. Feel free to connect with me on LinkedIn or GitHub, or read my personal website.
+This project is released under either
+the Creative Commons CC0 1.0 Universal
license
+and/or under the The Unlicense
license,
+at your discretion,
+whose verbatim copies can be found below.
The Unlicense
+-------------
+
+This is free and unencumbered software released into the public domain.
+
+Anyone is free to copy, modify, publish, use, compile, sell, or
+distribute this software, either in source code form or as a compiled
+binary, for any purpose, commercial or non-commercial, and by any
+means.
+
+In jurisdictions that recognize copyright laws, the author or authors
+of this software dedicate any and all copyright interest in the
+software to the public domain. We make this dedication for the benefit
+of the public at large and to the detriment of our heirs and
+successors. We intend this dedication to be an overt act of
+relinquishment in perpetuity of all present and future rights to this
+software under copyright law.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+For more information, please refer to <https://unlicense.org>
+
+Creative Commons Legal Code
+---------------------------
+
+CC0 1.0 Universal
+
+ CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE
+ LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN
+ ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS
+ INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES
+ REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS
+ PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM
+ THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED
+ HEREUNDER.
+
+Statement of Purpose
+
+The laws of most jurisdictions throughout the world automatically confer
+exclusive Copyright and Related Rights (defined below) upon the creator
+and subsequent owner(s) (each and all, an "owner") of an original work of
+authorship and/or a database (each, a "Work").
+
+Certain owners wish to permanently relinquish those rights to a Work for
+the purpose of contributing to a commons of creative, cultural and
+scientific works ("Commons") that the public can reliably and without fear
+of later claims of infringement build upon, modify, incorporate in other
+works, reuse and redistribute as freely as possible in any form whatsoever
+and for any purposes, including without limitation commercial purposes.
+These owners may contribute to the Commons to promote the ideal of a free
+culture and the further production of creative, cultural and scientific
+works, or to gain reputation or greater distribution for their Work in
+part through the use and efforts of others.
+
+For these and/or other purposes and motivations, and without any
+expectation of additional consideration or compensation, the person
+associating CC0 with a Work (the "Affirmer"), to the extent that he or she
+is an owner of Copyright and Related Rights in the Work, voluntarily
+elects to apply CC0 to the Work and publicly distribute the Work under its
+terms, with knowledge of his or her Copyright and Related Rights in the
+Work and the meaning and intended legal effect of CC0 on those rights.
+
+1. Copyright and Related Rights. A Work made available under CC0 may be
+protected by copyright and related or neighboring rights ("Copyright and
+Related Rights"). Copyright and Related Rights include, but are not
+limited to, the following:
+
+ i. the right to reproduce, adapt, distribute, perform, display,
+ communicate, and translate a Work;
+ ii. moral rights retained by the original author(s) and/or performer(s);
+iii. publicity and privacy rights pertaining to a person's image or
+ likeness depicted in a Work;
+ iv. rights protecting against unfair competition in regards to a Work,
+ subject to the limitations in paragraph 4(a), below;
+ v. rights protecting the extraction, dissemination, use and reuse of data
+ in a Work;
+ vi. database rights (such as those arising under Directive 96/9/EC of the
+ European Parliament and of the Council of 11 March 1996 on the legal
+ protection of databases, and under any national implementation
+ thereof, including any amended or successor version of such
+ directive); and
+vii. other similar, equivalent or corresponding rights throughout the
+ world based on applicable law or treaty, and any national
+ implementations thereof.
+
+2. Waiver. To the greatest extent permitted by, but not in contravention
+of, applicable law, Affirmer hereby overtly, fully, permanently,
+irrevocably and unconditionally waives, abandons, and surrenders all of
+Affirmer's Copyright and Related Rights and associated claims and causes
+of action, whether now known or unknown (including existing as well as
+future claims and causes of action), in the Work (i) in all territories
+worldwide, (ii) for the maximum duration provided by applicable law or
+treaty (including future time extensions), (iii) in any current or future
+medium and for any number of copies, and (iv) for any purpose whatsoever,
+including without limitation commercial, advertising or promotional
+purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each
+member of the public at large and to the detriment of Affirmer's heirs and
+successors, fully intending that such Waiver shall not be subject to
+revocation, rescission, cancellation, termination, or any other legal or
+equitable action to disrupt the quiet enjoyment of the Work by the public
+as contemplated by Affirmer's express Statement of Purpose.
+
+3. Public License Fallback. Should any part of the Waiver for any reason
+be judged legally invalid or ineffective under applicable law, then the
+Waiver shall be preserved to the maximum extent permitted taking into
+account Affirmer's express Statement of Purpose. In addition, to the
+extent the Waiver is so judged Affirmer hereby grants to each affected
+person a royalty-free, non transferable, non sublicensable, non exclusive,
+irrevocable and unconditional license to exercise Affirmer's Copyright and
+Related Rights in the Work (i) in all territories worldwide, (ii) for the
+maximum duration provided by applicable law or treaty (including future
+time extensions), (iii) in any current or future medium and for any number
+of copies, and (iv) for any purpose whatsoever, including without
+limitation commercial, advertising or promotional purposes (the
+"License"). The License shall be deemed effective as of the date CC0 was
+applied by Affirmer to the Work. Should any part of the License for any
+reason be judged legally invalid or ineffective under applicable law, such
+partial invalidity or ineffectiveness shall not invalidate the remainder
+of the License, and in such case Affirmer hereby affirms that he or she
+will not (i) exercise any of his or her remaining Copyright and Related
+Rights in the Work or (ii) assert any associated claims and causes of
+action with respect to the Work, in either case contrary to Affirmer's
+express Statement of Purpose.
+
+4. Limitations and Disclaimers.
+
+ a. No trademark or patent rights held by Affirmer are waived, abandoned,
+ surrendered, licensed or otherwise affected by this document.
+ b. Affirmer offers the Work as-is and makes no representations or
+ warranties of any kind concerning the Work, express, implied,
+ statutory or otherwise, including without limitation warranties of
+ title, merchantability, fitness for a particular purpose, non
+ infringement, or the absence of latent or other defects, accuracy, or
+ the present or absence of errors, whether or not discoverable, all to
+ the greatest extent permissible under applicable law.
+ c. Affirmer disclaims responsibility for clearing rights of other persons
+ that may apply to the Work or any use thereof, including without
+ limitation any person's Copyright and Related Rights in the Work.
+ Further, Affirmer disclaims responsibility for obtaining any necessary
+ consents, permissions or other rights required for any use of the
+ Work.
+ d. Affirmer understands and acknowledges that Creative Commons is not a
+ party to this document and has no duty or obligation with respect to
+ this CC0 or use of the Work.
+
+
+ APIs are a ubiquitous component of software engineering. APIs allow different components of a software system to interact with each other in a logical way.
+Learning about APIs is critical to your growth as a software developer. This guide contains links and advice to get you started!
+What is an API?
+ +API stands for Application Programming Interface, and in simple words, allows two applications to talk to each other and send information between the two.
+Further reading on the basics of APIs: https://www.plektonlabs.com/api-101-what-are-they-and-how-do-they-work/?gclid=Cj0KCQiAhf2MBhDNARIsAKXU5GRbLqWDWBPN0Zh4ZX6KwjevURl9KmQo0EVBzLn5mcePxaI_l1oWQSQaAkGDEALw_wcB
+Analogy of an API
+Imagine you are sitting in a restaurant with a menu and you are trying to decide what to order. You are one of the applications and in order to get food, the kitchen will act like the other application. It is the system that will “make” you food. The waiter in this scenario will be the API, and he/she delivers the food from one application(the kitchen) to another(you). The waiter is the messenger that takes your request or order and tells the kitchen – the system – what to do. Then the waiter delivers the response back to you; in this case, it is the food.
+How API’s Work
+Why would you need an API?
+Many companies have APIs built to allow others to build interesting applications using their company data. APIs also allows a project to be dynamic - it will update the frontend information automatically when the back end is updated. This saves the hassle of going through tons of HTML code updating data one by one.
+GraphQL vs Rest
+Reading In favor of GraphQl:
+https://www.howtographql.com/basics/1-graphql-is-the-better-rest/
+Reading In favor of Rest:
+https://www.rubrik.com/blog/technology/19/11/graphql-vs-rest-apis
+About
+https://www.ibm.com/cloud/learn/rest-apis
+A REST API is an API that conforms to the design principles of the REST, or representational state transfer architectural style. For this reason, REST APIs are sometimes referred to RESTful APIs.
+What is a RESTful API? https://www.youtube.com/watch?v=y0U-ZxgLu98
+Types of API calls
+ +Interactive Resource on APIs
+https://apiary.io/how-to-build-api#phase-design
+Tons of help on creating API with different languages https://rapidapi.com/blog/20-tutorials-on-how-to-create-your-own-api-sorted-by-programming-language/
+Explanations of API’s and more in depth language-specific resources
+https://www.moesif.com/blog/api-guide/getting-started-with-apis/
+What is Postman?
+Postman is a platform for building and using APIs. Postman simplifies each step of the API lifecycle and streamlines collaboration so you can create better APIs faster.
+Getting Started with Postman: https://www.guru99.com/postman-tutorial.html#1
+Good Postman Series starting with setting up: https://www.youtube.com/watch?v=juldrxDrSH0&ab_channel=AutomationStepbyStep
+Collection of Free, premade API’s
+Most premade API’s will have documentation of how to use/maintain them
+https://github.com/public-apis/public-apis
+ +Example of using a premade API
+https://rapidapi.com/blog/how-to-use-an-api/
+Further Help
+GraphQL Tutorial: https://www.youtube.com/watch?v=ed8SzALpx1Q&ab_channel=freeCodeCamp.org
+What is GraphQL (A really good article): https://www.redhat.com/en/topics/api/what-is-graphql
+Why use GraphQL: https://www.apollographql.com/docs/intro/benefits/
+Getting started with GraphQL: https://www.apollographql.com/docs/intro/benefits/
+GraphQL is split into two main parts, A Schema (Basically a model for the response), and a resolver (a collection of functions that generate response for a GraphQL query. In simple terms, a resolver acts as a GraphQL query handler)
+An article that explains what a Query, Mutation & Subscription are: https://medium.com/software-insight/graphql-queries-mutations-and-subscriptions-286522b263d9
+ +Django is a free and open source python framework that lets you build awesome backends for websites, apps, and more. You can use it to host databases and build secure APIs for them without writing a line of SQL. You can also use it to create multi-page applications with dynamically served content. It makes it easy to get started building complex functionalities by automating a lot of the boilerplate code that you'd normally have to write.
+We recommend that you have a basic knowledge of python before using django! This will help you debug any errors that you get.
+ +(Img src: https://medium.com/crowdbotics/when-to-use-django-and-when-not-to-9f62f55f693b)
+First you will need to install Homebrew, Python, Pip, and Pyenv. If you have not done so already, please follow the instructions in the Installfest section.
+To create a Django project first wee need to create a directory for the project. To do so, run the following command:
+mkdir <project-name>
+
+Then, we need to navigate to the directory we just created. To do so, run the following command:
+cd <project-name>
+
+Now, we need to create a virtual environment for our project. To do so, run the following command:
+pyenv virtualenv .venv
+
+Then, we need to activate the virtual environment. You need to do this every time you want to run your project. To do so, run the following command:
+source .venv/bin/activate
+
+If you want to deactivate your virtual environment when you're done working on your project, run the following command:
+deactivate
+
+Now, we need to install Django. To do so, run the following command:
+pip install django
+
+To check if Django is installed, run the following command:
+python3 -m django --version
+
+Next, let's create a project.
+django-admin startproject <project-name> . # the dot is important! it will create the project in the current directory
+
+Good to know: Projects vs. apps
+What's the difference between a django project and a django app? An app is a Web application that does something – e.g., a Weblog system, a database of public records or a small poll app. A project is a collection of configuration and apps for a particular website. A project can contain multiple apps. An app can be in multiple projects.
+
+python3 manage.py startapp <your-app-name>
+
+This creates an app within your project. You can create as many apps as you want within a project.
+Next step: include your app in the INSTALLED_APPS fields in settings.py (just the name)
+INSTALLED_APPS = [
+ 'django.contrib.admin',
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+
+ ...
+ 'your-app-name',
+]
+
+Dotenv is a zero-dependency module that loads environment variables from a .env file into process.env. Storing configuration in the environment separate from code is based on The Twelve-Factor App methodology. To install dotenv, run the following command:
+pip install python-dotenv
+
+Then freeze the requirements. To do so, run the following command:
+pip freeze > requirements.txt
+
+This will create a file called requirements.txt that will contain all the packages that are installed in your virtual environment. This file will be useful for when you need to install the same packages in another virtual environment. After adding a new package to your virtual environment, you will need to freeze the requirements again.
+Next, go to your project and create a .env file. To do so, run the following command:
+touch .env
+
+Then go to your settings.py file and add the following code:
+from django.core.management.utils import get_random_secret_key
+from dotenv import load_dotenv
+
+...
+
+load_dotenv()
+
+# SECURITY WARNING: keep the secret key used in production secret!
+# Copy the secret key from the .env file
+SECRET_KEY = os.getenv("DJANGO_SECRET_KEY", get_random_secret_key())
+
+Your .env file should look like this:
+DJANGO_SECRET_KEY=your-secret-key
+
+PostgreSQL is a powerful, open source object-relational database system with over 30 years of active development that has earned it a strong reputation for reliability, feature robustness, and performance. To install Postgres, run the following command:
+brew install postgresql
+
+To check if Postgres is installed, run the following command:
+postgres --version
+
+psycopg2 is a PostgreSQL database adapter for the Python programming language. To install psycopg2, run the following command:
+pip install psycopg2
+
+Then freeze the requirements. To do so, run the following command:
+pip freeze > requirements.txt
+
+Then go to your settings.py file and add the following code:
+INSTALLED_APPS = [
+ ...
+ 'psycopg2',
+]
+
+To create a Postgres database, run the following command:
+createdb <database-name>
+
+Remember your credentials for the database. You will need them later.
+It is also recommended to install pgAdmin, a free and open-source administration and development platform for PostgreSQL and its related database management systems. To install pgAdmin, run the following command:
+brew install --cask pgadmin4
+
+Add the following code to your .env file:
+DATABASE_NAME=<database-name>
+DATABASE_USER=<database-user>
+DATABASE_PASSWORD=<database-password>
+
+Now go to your settings.py file and add the following code:
+import os
+
+...
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.postgresql',
+ 'NAME': os.getenv('DATABASE_NAME'),
+ 'USER': os.getenv('DATABASE_USER'),
+ 'PASSWORD': os.getenv('DATABASE_PASSWORD'),
+ 'HOST': "127.0.0.1",
+ 'PORT': "5432",
+ }
+}
+
+Models allow you to define the content of your database. If you don't need content in your database, you won't need models.
+You can follow along with this section here:
+https://docs.djangoproject.com/en/3.1/intro/tutorial02/
+More about models: https://docs.djangoproject.com/en/3.1/topics/db/models/
+You will define all your models in models.py, located within the folder for your app.
+from django.db import models
+
+# Create your models here.
+class Album(models.Model):
+ name = models.CharField(max_length=200)
+ artist = models.CharField(max_length=100)
+ year_released = models.DateField()
+ def __str__(self):
+ return str(self.name)
+
+class Song(models.Model):
+ song_name = models.CharField(max_length=100)
+ album = models.ForeignKey(Album, on_delete=models.CASCADE)
+ num_streams = models.IntegerField()
+ def __str__(self):
+ return str(self.song_name)
+
+Each model should correspond to the structure of a table of a relational model of a database. If you don't know what this means, ask someone who has taken CPSC 471 (or an equivalent databases course)
+Django can convert these into real SQL tables!
+There are more options that can be explored about how you can define your models, but this should be a good base for you to do your own research :)
+Now we're ready to convert these into a real database! By default, Django will make a migration file that has your database.
+Converting models into your database
+
+https://docs.djangoproject.com/en/3.1/intro/tutorial02/
+
+>> python3 manage.py makemigrations appName
+Creates migrations for the changes you made in appName
+
+>> python3 manage.py migrate
+Migrates the changes you made into your database
+
+
+Whenever you are ready to run your server, just call this command!
+python3 manage.py runserver
+
+You should see something like this:
+ +By default, this will run the Django server on localhost:8000. View the django documentation to see how you can run it on a different port. You can now access it from your web browser by visiting http://localhost:8000 !
+You can also create a superuser (admin) to view the inner contents of your database. To do this, you first need to create them from the command line using the following command:
+python3 manage.py createsuperuser --username yourNameHere --email yours@email.ca
+
+This will create a super user with your provided info (it will prompt you to enter a password as well).
+The following command creates a token for the superuser that you can use for authentication in requests. If you are not using Django Rest Framework, this is not applicable to you.
+python3 manage.py drf_create_token yourSuperUserName
+
+Note: if you're trying to run these for your deployed app on heroku, you need to prepend heroku run
before those commands! See the Heroku section for a description on how you can deploy it.
You can see the admin page of your website to view the inner content of your database. This is automatically created by Django. Visit http://localhost:8000/admin and enter your passcode.
+If you want your models to show up in the admin page, you will need to specify them in admin.py like this:
+from django.contrib import admin
+from .models import Album, Song
+# Register your models here.
+
+admin.site.register(Album)
+admin.site.register(Song)
+
+Once you log in to the admin site, you should see something like this. From here, you can add & remove database entries. +
+URLs allow you to define the paths that exist in your system, and what happens when you call them.
+URLs documentation: https://docs.djangoproject.com/en/3.1/ref/urls/
+How URLs are processed in Django: https://docs.djangoproject.com/en/3.1/topics/http/urls/#how-django-processes-a-request
+Read more: https://docs.djangoproject.com/en/3.1/intro/tutorial03/
+If you're constructing a big application, it's standard practice in django to include different _apps _for each part of your system, and link them to the main project.
+ +However, since we're only making small-scale side-projects, it's fine to ignore this best-practice and include everything in a single app. Just understand that in a large industrial scale project you wouldn't necessarily want to do this.
+// urls.py in a project:
+from django.contrib import admin
+from django.urls import path, include
+
+urlpatterns = [
+ path('admin/', admin.site.urls),
+ path('myApp/', include('myApp.urls'))
+]
+
+// example urls.py in myApp folder:
+from django.urls import path
+from . import views
+
+urlpatterns = [
+ path('hello_world', views.ping, name='Hello World!'),
+ path('hello-x/<str:hello_to>', views.hellox, name='Hello to x'),
+ path('hello-x/<print_me>/print', views.printx, name='Print this!'),
+ path('goodbye', views.goodbye, name='goodbye'),
+]
+
+Now you can visit a path using http://localhost:8000/myApp/hello-world, for example.
+**Views **allow you to define what happens when you access a certain url in your system (using your browser, an API tool like Postman, or something else altogether). In your views, you could define interactions with the model (your database) or entirely different interactions altogether. You can use the definition of the view to call external processes.
+If you want to make more complicated views and understand the Request and Response items, read this:
+https://docs.djangoproject.com/en/3.1/ref/request-response/
+To understand views more in-depth, read the documentation: https://docs.djangoproject.com/en/3.1/topics/http/views/
+Here are some simple examples of what you can do with a view. Note that these are just examples and don't represent best practice at all.
+from django.http import HttpResponse, response
+# views.py
+def ping(request):
+ myRes = "Hello World!"
+ return HttpResponse(myRes)
+
+def hellox(request, hello_to):
+ myRes = {"My Reply": "Hello " + hello_to}
+ return response.JsonResponse(myRes)
+
+def printx(request, print_me):
+ print("Hello to " + print_me)
+ return response.HttpResponseNotFound("I printed it!")
+
+def goodbye(request):
+ if not (request.method == 'GET'):
+ return response.HttpResponseBadRequest()
+ queryParams = request.GET
+ msg = queryParams.get('msg', "Gamers")
+ return response.JsonResponse({"Reply": "Goodbye " + msg})
+
+Now, we want to adhere to DRY (Don't repeat yourself) when creating views. Therefore, it is almost always best to define your views as Class-Based views (CBVs) which handle more of the boiler plate code for you and help ensure your views follow standards.
+Please read more about class-based views here: https://docs.djangoproject.com/en/3.1/topics/class-based-views/
+Both the above docs and the docs for views also show how you can interact with your database items through a view. But, if you're building an API, I highly recommend using the tools in the following section: Django REST Framework.
+Once you have defined your views and given them a corresponding url, you can test them out.
+python3 manage.py runserver
+
+Run your server, and using either a web browser, or preferably an API testing tool like Postman (https://www.postman.com/) access the proper urls (ex. http://localhost:8000/myApp/hello_world) to see if they have the expected behavior.
+Django REST Framework is an add-on to Django that makes it simple to develop REST-compliant APIs. There is great documentation here: https://www.django-rest-framework.org/ <--- FOLLOW INSTALL INSTRUCTIONS
+What is a RESTful framework? Learn more here: https://restfulapi.net/
+Django REST Framework provides you with tools to make class-based views to easily implement database CRUD (Create Read Update Destroy) operations, as well as define more complex operations.
+Before we define any endpoints with Django REST Framework, let's make some serializers.
+ +Django REST Framework uses serializers as a way to perform **translation **of your models from your python code and your database into data formats like JSON and XML that an API might use. Read more about them here:
+https://www.django-rest-framework.org/api-guide/serializers/
+We should define some basic serializers so that we can make API endpoints that interact with the content of our database models.
+Here's an example, using the Song and Album models we defined earlier. Here's what's at the top of serializers.py:
+from rest_framework import serializers
+from .models import *
+
+class SongSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Song
+ fields = ("id", "song_name", "num_streams")
+
+class AlbumSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Album
+ fields = ("name", "year_released", "artist", "id")
+
+Make sure your fields match exactly the names that you used in your models.
+You may be curious why I also included an id, when we didn't define one in our models- this is because Django auto generated an id for us in this models because we didn't specify a primary key. This id field always has the name id. It is often useful for our API, so we'll include it.
+We can also create multiple serializers for the same models, if we wanted different behavior. For example, what if we wanted to include the album id of the song?
+class SongSerializerWithAlbumId(serializers.ModelSerializer):
+ class Meta:
+ model = Song
+ fields = ("id", "song_name", "num_streams", "album")
+
+This would include the album's PK (in this case, it's id, but if the PK was different, it'd be something else).
+What if we wanted to include the full album info when an api request was made to see the song? Here's another example serializer that we could make:
+class SongSerializerFullAlbum(serializers.ModelSerializer):
+ myFullAlbumDesc = AlbumSerializer("album", read_only=True)
+ class Meta:
+ model = Song
+ fields = ("id", "song_name", "num_streams", "myFullAlbumDesc")
+
+It's using our album serializer from earlier to serialize a field, which must (read only is an optional parameter that makes it so that it's only included in reading requests, not create/update/destroy.)
+This was just an introduction to serializers. If you want to use more complex behaviors, you'll have to do the research on your own.
+Pre-requisite to this section: understand URLS and views in vanilla Django, and read the serializers section
+
+More reading: https://www.django-rest-framework.org/tutorial/3-class-based-views/
+Video overview of similar topic: https://www.youtube.com/watch?v=akvFA5VMXJU
+You can use Django's Class Based Views to quickly create views that can do CRUD (Create, Read, Update, Destroy) operations on your database.
+In views.py:
+from rest_framework.views import APIView
+from rest_framework import generics
+from rest_framework import status
+from .models import *
+from .serializers import *
+
+Some class based views that we'll define. Right now these are just the generic create, read, update, destroy views. By defining these views with the classes, Django REST Framework takes care of the default behavior for us. It's that easy!
+class SaveSong(generics.CreateAPIView):
+ queryset = Song.objects.all()
+ serializer_class = SongSerializerWithAlbumId
+
+class GetSongs(generics.ListAPIView):
+ queryset = Song.objects.all()
+ serializer_class = SongSerializer
+
+class DeleteSong(generics.DestroyAPIView):
+ queryset = Song.objects.all()
+ serializer_class = SongSerializer
+
+class UpdateSong(generics.RetrieveUpdateAPIView):
+ queryset = Song.objects.all()
+ serializer_class = SongSerializerWithAlbumId
+
+Notice that we need to make the create and update serializers include the album ID- if we didn't then you couldn't create song objects since their album id must be _not null._This same principal applies to any model that has a foreign key which isn't allowed to be null.
+Before we can use the views we created, we need to hook them up to a URL, just like you would for any other view. Do keep in mind that we need to call the as-view function on them, though. Here is an example of the URLs for the previous views. This pattern is how we normally define CRUD endpoint urls for any entity in a database
+ path('song', views.GetSongs.as_view(), name='songs'),
+ # Create a song
+ path('song/create', views.SaveSong.as_view(), name='Save Song'),
+ #Updates a specified license with information
+ path('song/<int:pk>', views.UpdateSong.as_view(), name='Update Song'),
+ # Deletes a song specified by pk
+ path('song/<int:pk>/delete', views.DeleteSong.as_view(), name='Delete Song'),
+
+If you are using a pk that is not an int (you manually defined a pk instead of using the default id generated), you'll have to specify that accordingly.
+What if we want more complex behavior beyond the default predefined classes? We can modify them to add more conditions to what is returned.
+In this example, we added an optional way to filter songs by album, using a query_param called album. You'll need to read documentation and tutorials if you want to know more about the custom behavior you can define within your Django REST Framework views.
+class GetSongInAlbum(generics.ListAPIView):
+ serializer_class = SongSerializer
+ def get_queryset(self):
+ queryset = Song.objects.all()
+ alb = self.request.query_params.get('album', None)
+ queryset = queryset.filter(album=alb)
+ return queryset
+
+If you have a view that isn't necessarily linked to CRUD actions, or has more complex usage and needs more custom defined behavior, you can use APIView.
+Compile and run your app with
+python3 manage.py runserver
+
+Use your bugfixing wizardry to fix any errors that might show up. Now you should be ready to give those predefined endpoints you made for a spin!
+Here's some examples that I did using Postman for API testing. If you used Django REST Framework, it should also come with a built-in API testing tool that you can use in your browser.
+Here's a simple GET request. This is a database read operation, and it's pretty simple. Your browser is making GET requests to every URL you visit while you surf the web.
+Request + | ++ + | +
Response + | ++ + | +
Here's a POST request (it's post because we're _creating _or Posting new data) to our create route. We should include the key-value pairs for the song we want to create in the **_Body _**of our request.
+Request + | ++ + | +
Response + | ++ + | +
To update, let's follow the URL pattern we defined with the pk of the song we want to update. We can use PUT or PATCH. The info you're sending should be in the _Body _of the request, just like it was for our POST request.
+Request + | ++ + | +
Response + | ++ + | +
Let's do the same thing for our deleteSong view, but let's delete Taylor's song this time (pk: 2). I'm sure it was no good anyways.
+Request + | ++ + | +
Response + | ++ + + | +
Let's use our GET view to see what's inside the DB now:
+ + +**unimportant note: in my zeal to delete taylor's song I had a mishap and accidentally deleted song 3, which I have readded here using a post request. but it's id is now 5 :[
+Finally, let's try out that "song with album" route. We'll add it to our urls.py:
+ # Probably not the best naming convention
+ path('songInAlbum', views.GetSongInAlbum.as_view(), name='Get song in album'),
+
+
+Here's what our request will look like. ^^^^^^^^
+Here's the response:
+ +Good to know: Query Parameters
+Notice how our query params don't have to be specified in urls.py - they are dynamically generated from the URL that we try access (everything that comes after a ? in a url is a query parameter, with keys and values separated by '='. If you had multiple query parameters they would be separated by '&'. Next time you're browsing the web, notice how query parameters are used across the different websites you visit!
+It's easy to access query params within Django - see the getSongInAlbum view definition for an example.
+
+Up to now, we've covered the fundamentals of how to create a database, populate it, and create simple endpoints for creating, updating, and destroying. But what happens when we want our system to be used by real users? How do we store their information and their interactions with our system? There are a few important issues that we'll need to address:
+The answer to these questions can be complicated. In order to save your time and energy, we're going to utilize the resources that Django and Django REST Framework provide for us as much as possible instead of developing our own solutions. Not only is this easier, but it's also much more secure- would you trust a system written from scratch by a novice undergrad student with your password and financial information?
+How do we store user's personal info?
+The answer to this question is usually to use Django's built-in User model. You can read the docs on User models here:
+https://docs.djangoproject.com/en/3.1/ref/contrib/auth/
+The User model contains common fields that will be used by users, and in your serializers you can define which fields are relevant to your use case.
+By default, Django builds the User models for you. You can see them after you runserver and check inside the /admin route.
+We can also utilize the User model to build new endpoints in our API, just like we could with any other model. Here's an example:
+from django.contrib.auth.models import User
+
+…
+class UserLikesSong(models.Model):
+ user = models.ForeignKey(User, on_delete=models.CASCADE)
+ song = models.ForeignKey(Song, on_delete=models.CASCADE)
+
+class UserLikesSongSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = UserLikesSong
+ fields = ("id", "user", "song")
+ #Id of the rel, Id of the user, ID of the song
+
+You can now make endpoints with this just like you would with any other model/serializer. This specific example could be used to track what songs the User likes, like in Spotify.
+If you wanted to make a custom User model, you could read more about it here https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html and do more research, as there are many methods you could use. For basic university usage though, it's 99% of the time going to be faster and easier to roll with the User model they give you out of the box.
+If you want to give different categories of users different permissions, see the_ permissions _section (TODO: this won't be done for a while. In the meantime, these links may help: https://www.django-rest-framework.org/api-guide/permissions/ ← Technical overview
+https://www.django-rest-framework.org/tutorial/4-authentication-and-permissions/ ← Basic usage example)
+Signup, Login, Sessions: How do we do them?
+I highly recommend using Django REST Framework's Authtokens to handle information about user sessions. You can read about authtokens, as well as the other options available, here: https://www.django-rest-framework.org/api-guide/authentication/#tokenauthentication
+To add Authtoken's, make sure the following items appear in settings.py:
+###### You will need to add the REST Framework part.
+###### INSTALLED_APPS should already exist.
+
+REST_FRAMEWORK = {
+ 'DEFAULT_AUTHENTICATION_CLASSES': [
+ 'rest_framework.authentication.TokenAuthentication',
+ ],
+}
+
+INSTALLED_APPS = [ # There will be more here
+ 'rest_framework',
+ 'rest_framework.authtoken',
+]
+
+
+
+Note: I couldn't get these to work, at least not with authtoken. Leaving them here in case some enterprising individual finds them useful, or message us on Discord if you figure this out :)
+To get REST Framework's default login and logout views (prebuilt), type this in your project's root urls.py file:
+ urlpatterns = [
+ ...
+ path('api-auth/', include('rest_framework.urls'))
+]
+
+Your path doesn't have to be api-auth, it can be whatever you want.
+To use REST Framework's login view, include this in urls.py:
+ path('whateverPathYouWantToLogin', obtain_auth_token, name='API Token Login'),
+
+Include this at top of your urls.py:
+from rest_framework.authtoken.views import obtain_auth_token
+
+When you access this path and provide a real username and password in the request body, then you should receive an authtoken. This authtoken is associated with your account. Store this authtoken in a safe place. Now, you can use it in the "authorization" section of your next HTTP requests, and all requests you make from the client will be associated with the account you just logged in from.
+Creating views for signing up is more difficult.
+In serializers.py:
+
+
+
+
+
+
+
+
+
+
+
+ +This serializer will make sure that the password that the user makes is valid, and that it's write-only for security purposes. Choose which fields us + |
+
In views.py:
+
+
+ +… +
+
+
+
+
+
+ |
+
In urls.py:
+
+ +(you may want to put your register / login views together in a different Django App (so they are in a distinct section of your API) + |
+
Test Request in Postman:
+ + + +Response from request: + + + |
+
Now let's quickly do a login from this user we just created!
+I did a login request to the login view I made earlier, but here's what I got:
+ +Whenever you see an error like "no such table", that should be a clue that you need to rerun migrations. The app expected there to be a SQL table, but there was none made yet! Running migrations will ensure there is. Recall the commands for migrations are:
++++++
python3 manage.py makemigrations yourAppName
+++++
python3 manage.py migrate
In this case, just the second command will be sufficient
+Request:
+ +Response:
+ +Yay! It worked! Now we can include this token in our request headers to associate all future requests made with the user we logged in.
+In future requests, you should put the token as a value in your request headers, using the key: token.
+ +
+Depending on the front-end you build, you should use a different way to store the authtoken that you get from logging in. Usually storing in local memory is okay. Do your own research for how to store authtokens with whatever system you are using.
If you want to improve security further, you can use JWT (JSON webtoken) instead, following the instructions here: https://simpleisbetterthancomplex.com/tutorial/2018/12/19/how-to-use-jwt-authentication-with-django-rest-framework.html
+How do we make endpoints behave differently depending on which user is accessing them?
+If a user makes a request while they are authenticated (using authtoken, or some other alternative method), then the system will automatically know what user is associated with the user who made the request.
+You can access the user within a class-based view through
+ self.request.user
+
+You can use this within your views in a variety of ways: to filter, to make more complex queries, and to check if the user should have access.
+For example, let's make a UserLikesSong endpoint that is limited to the songs that the currently logged in user has liked.
+class GetUserLikesSongs(generics.ListAPIView):
+ def get_queryset(self):
+ queryset = UserLikesSong.objects.all()
+ queryset = queryset.filter(user=self.request.user)
+ # Leftside of filter: from queryset. Rightside: how we're filtering
+ return queryset
+ serializer_class = UserLikesSongSerializer
+
+We'll cover this in much more detail in the Permissions section.
+NOTE: Everything past here is incomplete - you will need to supplement it with your own research, like I did to make this guide!
+
+To use generic permissions with Django, all you need to do is:
+from rest_framework.permissions import IsAdminUser, IsAuthenticated, IsAuthenticatedOrReadOnly
+
+Now, on any class-based view you want to guard with permissions, you can add the following line:
+class deleteLicenseType(generics.DestroyAPIView):
+ permission_classes = [IsAdminUser]
+ queryset = License_Type.objects.all()
+ serializer_class = License_TypeSerializer
+
+(this is from a different project)
+You can apply multiple permissions to the same view like this:
+ permission_classes = [IsAdminUser|IsAuthenticatedOrReadOnly]
+
+Sessions/cookies are very easy to make use of with Django. You can use cookies to store information in a user's browser that you'll be able to access in all subsequent requests that a user makes. One example of a good use of sessions/cookies is to store a user's shopping cart content.
+Some great videos for learning about sessions & cookies:
+https://www.youtube.com/watch?v=C75IW38hKI8
+https://www.youtube.com/watch?v=RjykNmVdcgI
+ +To get your projects online, you can deploy them to Heroku. Heroku is just one of several possible hosting services for Django- but it's base tier is free, easy to use, and simple to deploy to, so that's what I recommend you use. The biggest downside of using Heroku is that its free tier will automatically shut down your app after a period of downtime, meaning it'll take a long time to respond the next time you try to access it.
+A guide on getting started:
+https://devcenter.heroku.com/articles/django-app-configuration
+Some useful commands:
+++++pip install gunicorn
+
To deploy to Heroku, you will need to make a file called Procfile (no file ending), and add the following gunicorn text to it:
+web: gunicorn yourAppName.wsgi
+
+This gunicorn file should be at the same level as your manage.py file. When you deploy to Heroku, you should be deploying from this level of the project hierarchy to avoid issues.
+Your remote heroku environment needs to understand what requirements it will need to have to start up. You can do this by providing it with a requirements.txt file which will also be at the same level as your manage.py file.
+To get the right requirements in a .txt file, type
+++++pip freeze > requirements.txt
+
These commands will help initialize your heroku repository:
+++++heroku create
+
++++heroku run python3 manage.py migrate
+
++++heroku run python3 manage.py createsuperuser
+
Important: Your database itself will not transfer to Heroku. You will need to recreate all entities, config, and users.
+ +Unless otherwise stated, all git commands are one line terminal commands
+We are also assuming that you have set up a project at /path/to/project
and had cd
'ed to /path/to/project
A Git Repository is virtual storage of your code, allowing you to save versions of your code, as well as share and allow others to edit the code.
+Initializing a new repository: git init
Cloning an existing repository: git clone [GitHub git link]
E.g. git clone https://github.com/techstartucalgary/tsu-website.git
<> Code
dropdownImagine that we have two people working on the same paper remotely, Person A and Person B. Person B is the laziest of the two, so Person A starts the paper.
+Person A choses to create a word document on their local machine. This can be seen as Initializing a new repository.
+After working on the paper for a bit, they realize that Person B also needs to contribute, so they send the paper by email to Person B. This step is equivalent to forking a repository.
+Person B decides that they would prefer to work on the paper by hand, and so they takes the email that Person A sent, and prints it to work on, cloning the repository
+There are a number of great GUI (graphical user interface) tools that simplify the process of +using Git, like GitHub Desktop, GitKraken, and the built-in Source Control tab in VSCode. +There's nothing wrong with using these tools, but we like to encourage our members to use the +command line in order to get a better understanding of what exactly you're doing. It's also universal, +so whatever you learn here can be used in any organization that uses Git!
+Git works using units of change called commits
. These commits are essentially snapshots of your project. To share any changes, additions, and deletions that you make with other people and upload it to the internet, you will need to package them into a commit first.
You can think of the staging area of git (the green box that says "staged changes" in the below diagram) like a box. You can add and remove changes from the box on a per-file basis.
+Committing is like sealing that box and sticking a label on it. The contents of that box are your changes. But, if there are changes in the untracked or unstaged areas, they will not be included in the commit, because they are outside of the box.
+The following diagram shows how the staging process works, and what commands you can use to move changes (again, per-file basis) between areas. Use the git status
command to see a summary of where every change in your project is on this diagram! We recommend using git status
frequently.
Here are some common commands for using Git to store and prepare the code to be pushed to the remote repository. +They are shown in the general order that you want to use them in.
+Below is the legend for some common, optional parameters which are shown
+git command -text
)git command helloWorld
)git add [path]
, you should replace [path]
with path/to/your/file
, so the final command is git add path/to/your/file
git status
Shows the status of all changes (all staged or unstaged changes, not committed changes). It shows where every change is on the diagram above, and even lists some helpful commands.
+It will also say what branch you are on, and if you are ahead or behind the remote version of your branch in terms of commits (more on this in later sections).
+Additionally, if you have a merge conflict, it will show which files caused it.
+git add [path/to/file]
+++
git add app/pages/HomePage.tsx
Selects the specified files, moves it to the “staging area” to be included in the next commit.
+This command will also allow adding a deleted file to be staged, which after being committed and pushed will remove the file from the git branch.
+This command will ignore all files in the “.gitignore” file.
+[path/to/file]
File path expression. Any files which match the expression are acted upon by git add
+git add -p
to add parts of a changed file if needed.git add -A
to add all changed files! Read about why you shouldn't always do this.git commit -m "[commitMessage]"
+++
git commit -m "Updated homepage text"
Creates a new commit that includes all changes that you added to the staging area.
+You always need to include a commit message (-m
) for your commit . It is helpful to be as descriptive as possible!
If you don't use the -m
flag and provide a commit message in quotations, Git will make you write a commit message using a text editor. However, this can be very confusing since your default Git text editor is often configured to be VIM (stuck in VIM? type :qa
to exit). For this reason, we recommend always specifying the commit message using -m
.
After you commit, these changes are no longer in the staging area - they are in your commit!
+(-m
) means you will be specifying a commit message in quotations
"[commitMessage]"
the message that will be attached to the commit. Only usable if -m
is used, otherwise a text editor will appear for the commit message.
Tip: always wrap your message in double quotes ("
). This lets you use abbrevations in your message (... -m "Reverted Ben's Changes"
)
git restore [path/to/file]
+++
git restore app/pages/HomePage.tsx
Discards local changes in a file, thereby restoring its last committed state.
+Think of it like a super-undo, allowing you to quickly get rid of accidental or unnecessary changes, restoring your files to how they used to be before you changed them.
+It won't work if your file is already staged - you'll have to unstage it with git restore --staged [path/to/file]
first.
git restore --staged [path/to/file]
+++
git restore --staged app/pages/HomePage.tsx
Removes the file from the Staging Area, but preserve all modifications you made to it. +You can use it if you accidentally added a file to the staging area whose changes shouldn't be included as part of the next commit you are planning to make. +If the file was originally untracked, it becomes untracked again. If it was originally a file with unstaged changes, the changes become unstaged again.
+When you create a commit, you always want to include a descriptive name for the commit that describes exactly what it accomplishes. You wouldn’t label a moving box with kitchen items as simply “stuff”. +Remember that other people will see these commit names, so make it easy for them to understand!
+For a video tutorial on staging files, watch this
+If you want to learn about additional flags and commands you can use in the process of staging files and adding commits, see the section Advanced Staging & Commits
+Branches represent an independent copy of the code that has branched off the main code at a certain time. +They allow new features to be worked on, while ensuring that a working version of the code is not tampered with. +This allows large changes to be made to the code base, with little fear of breaking your projects.
+git branch
Lists all branches in the current repository
+git branch [branchName]
+++
git branch ben/updateFont
Creates a branch called branchName
in the current repository.
The created branch's commit history will match the branch you were on when you called git branch
.
We recommend naming branches according to what you want your branch to do, prefixed by your name.
+For example, if I was updating the font on a website, I might call my branch ben/updateFont
.
+Since branch names include whitespace, we recommend using camelCase to name them, but check with your PM
+how they want to handle this.
git branch -d [branchName]
+++
git branch -d ben/updateFont
Deletes the branch called branchName
Note: you cannot delete the branch you are one! git checkout
to another branch first.
(You can use -D
instead of -d
to force delete the specified branch, even is it has unmerged changes.
+It's typically better to use -d
, unless you are 100% sure you will never need the branch you are deleting again)
git checkout [branchName]
Navigates your current directory to the specified branch, allows you to select which line of development you are working on.
+You can only switch branches if you have no unstaged/staged changes in your current branch. If you can't switch branches because of this, see What happens if you can't checkout? for more instructions.
+Pro tip: You can use git checkout -b [branchName]
to create a branch and switch to it immediately.
Some rules (more like guidelines):
+main
Before you make your branch, you should make sure you are creating your branch based on the most recent code. Do git checkout main
to switch to the primary branch of your repository. You should also do git pull
to make sure the primary branch is up to date with the version present on your remote repository (more on this in the next section).
Now that you are on the primary branch, use git branch [branchName]
to create a new branch based on the current one. Make sure you name it according to what you aim to accomplish there (see the description of the command above).
Now that you have created your branch, you'll want to switch to it. Use git checkout [branchName]
to switch to your branch. You can do work here and follow the instructions in the staging files and creating commits section to save your changes into commits.
Eventually, you'll be done using the branch (perhaps you will follow the instructions in the next few sections to push it to your remote repository and use it in a pull request. or perhaps you need to work somewhere else). Either way, you can switch to a different branch with git checkout [branchName]
If you have completed a pull request for your branch to merge it into a different branch of your project, you no longer need to keep the local copy of your branch. We recommend you use git branch -d
to delete any branches you will no longer need to use. This makes sure your local repository remains nice and tidy.
Here's a quick summary of the commands:
+git checkout main
+git pull
+git branch ben/updateFont
+git checkout ben/updateFont
+... doing stuff ...
+git checkout main
+git branch -d ben/updateFont
+
+
+Git will not let you checkout to switch branches if you have staged or unstaged changes.
+You will have a few choices on what to do:
+git restore
, described in the previous section). Do this if any of your changes are unnecessary or accidental.main
)! All Tech Start repositories actually prohibit commits to main
to prevent this.git stash
to move changes from one branch to another without needing to commit them. Do this if your changes are intentional, but you wanted them on a different branch than the one you are currently on. This is described in more detail here.You can combine these approaches to deal with your changes as necessary.
+When you work with Git, you will typically have a local repository (the copy of your project that exists on your personal device) and a remote repository (the copy of your project that exists on the internet, usually on a service like GitHub, GitLab or BitBucket)
+An absolutely core part of using Git is managing the interactions between your local repository and the associated remote repository. The two key commands you will need to learn are git push
(which you can use to push commits from your local repository to the remote repository)
+and git pull
(which you can use to pull commits from the remote repository and insert them into your own local repository).
A common mistake that newcomers to Git will make is assuming that the local repository is the same as the remote repository - when they're actually 2 separate concepts. Your commits won't appear on the remote repository until you manually push them there. If someone else pushes new changes to the remote repository, you won't see their changes on your local repository until you manually pull those changes to your device.
+Most version control related work happens in a local repository(staging, committing, viewing status, etc.). +Remote repositories come into play when you start working with others on the same project. +You can think of it as a cloud file server that you use to collaborate with others.
+ +Local | Remote |
---|---|
Are located on the computers of the team members | Are on the internet or a local network |
Contains branches, commits, tags | Contains branches, commits, tags |
All “coding work” happens only in the local repository, and needs to be made and committed locally. | After the work has been committed locally, it can be “uploaded” to the remote repository in order to share with others. |
Note: You can name a local branch the same name as the remote branch, but they are NOT the same
+Note: You can also have multiple remote repositories (default is origin
), though you probably won't need this,
+since each local repository stores what it's remote is.
git fetch
is what you do when you want to see what everybody else has been working on. It doesn’t force you to actually merge the changes into your repository. This makes fetching a safe way to review commits before integrating them with your local repository.
You might be wondering how to set a remote, and the good news is that if you cloned your repository from GitHub,
+it's been set for you, so no need to worry!
+If you need to change the remote for some reason, you can do git remote set-url origin <url>
git pull [remoteName] [branchName]
git pull origin ben/updateFont
Pulls all changes/commits from the specified remote branch, and inserts them into your current branch.
+Pro tip: Use git pull
without any other options to update the branch you're on. You'll most likely only use this to update main
.
More technical description: fetches from the remote branch (git fetch
), and merges your current branch with commits from the remote (git merge
)
[remoteName] [branchName]
pulls from a specific branch, which you specifygit pull origin main
Fetches commits from the master branch of the origin remote (into the local origin/master branch), and then it merges origin/master into the branch you currently have selected
+git push
Updates the remote branch with your staged, local commits
+Always pull
before push
ing to a branch to avoid unwanted merge conflicts and errors..
Conflicts generally arise when two people have changed the same lines in a file, or if one developer deleted a file while another developer was modifying it. In these cases, Git doesn't know which change is correct. Git will mark the file as being conflicted and halt the merging process. It is then the developers' responsibility to resolve the conflict.
+Although they look scary, resolving merge conflicts is a completely normal part of working collaboratively.
+The general steps for resolving merge conflicts can be seen as:
+Some useful commands for attempting to fix merge conflicts
+Command | Description |
---|---|
git status | Help identify conflicted files |
git log --merge | Produces a log with a list of commits that conflict between the merging branches |
git diff | Finds the differences between the states of a repository, which helps in preventing conflicts |
git reset --mixed | Undo changes to the working directory and staging area |
In this case, there are two instances of the file “merge.text” that were modified by different branches/people. Git is unable to determine which lines to keep, as both were changed manually.
+Git will notify you if there are any merge conflicts after running git status
. You can identify these conflicts by looking at your project files. Conflicted files will have markers like <<<<<<< HEAD
, =======
, and >>>>>>> [branch name]
where the conflicting changes are.
Use a text editor or an integrated development environment (IDE) like VS Code to open the conflicted file. Inside, you will see the conflicting sections clearly marked by symbols.
+Review the conflicting sections and decide which changes to keep. You can choose to keep your changes, the incoming changes from the other branch, or a combination of both. Make your edits, then remove the conflict markers (<<<
, ===
, >>>
).
<<<<<<< HEAD
+// Your changes
+=======
+// Incoming changes
+>>>>>>> [branch name]
+
+Once you've resolved the conflict, save the file.
+Use git add
command to stage the resolved file.
After resolving all conflicts, use git commit
to finalize the merge.
git commit -m "Resolved merge conflicts"
git push
your changes to the remote repository.
Merge conflicts can be complicated to resolve, so make sure you communicate with the person who created +the branch you have a conflict with to ensure you don't lose their work.
+Remember that Incoming
changes are from the other branch, while Current
changes are from your branch.
It also doesn't hurt to use a tool that's purpose-built to resolve merge conflicts. +VS Code has one built in, but there are a number of free options available online.
+GitHub is a company that provides a service of hosting Git repositories online. There are many other alternative companies that provide a similar service, like BitBucket, GitLab, and Azure DevOps, but GitHub is the most popular one and the one our project teams use.
+The instructions for the rest of this section will focus on GitHub's features. However, almost every feature described here has equivalents in the other git hosts, so if you know how to use one you generally know how to use them all.
+A pull request is a way of merging code from one branch of your remote repository into another.
+ +You are requesting that the base branch pulls the commits from the compare branch. +In the above example, you are requesting that the main branch pulls the commits from the addLaunchEvent. +In other words, you are taking the changes from compare and putting them into base.
+You will use pull requests extensively as part of your Git workflow.
+We encourage teams to use small, frequent, single-feature PRs. Ideally each PR should be associated with only one branch, and each branch to only one PR. Each PR should have a name that describes exactly what the PR accomplishes. By doing smaller PRs, you will make sure everyone frequently updates their codebase so you don't end up with massive merge conflicts. By limiting your PR to a single feature, you also make it super easy to roll back that feature and reverse all commits in the PR by reverting the PR itself.
+Advantages of pull requests:
+Sometimes, when you create a pull request, it will say there is a merge conflict. If this happens, don't force the PR to merge! Instead, you'll want to resolve the merge conflict.
+Steps:
+git checkout addLaunchEvent
git pull origin main
git push origin addLaunchEvent
Additional readings on pull requests:
+ +https://product.hubspot.com/blog/git-and-github-tutorial-for-beginners
+https://yangsu.github.io/pull-request-tutorial/
+One of the main advantages of pull requests is that they enable you to do a pull request review, ensuring that code that gets pulled into your primary branches has been reviewed by your team to make sure it won't introduce code smells or bugs.
+PRs provide the opportunity to review another developer's code and make sure that it meets the guidelines or practices that your organization or team has. For example, if you have a developer who is more familiar with the architecture of the software system, they can provide valuable input towards making sure that your changes fit within the long term architectural vision of the system. +Alternatively, you can have a newer team member who is not yet familiar with the overall code structure and they can add comments to specific parts of the code in a PR to ask for further clarification for why a certain change was made.
+Aside from learning, PRs generally serve as a major communication channel for developers in industry, because they provide the opportunity for automated testing and improvements before your code changes are moved to the next deployment stages. One example of automated testing is using linter which is a static code analysis tool used to flag errors in your code such as bugs, stylistics errors, and suspicious constructs, like for example declaring a variable twice.
+Whenever someone wants to merge a pull request, you should require them to get their PR reviewed first. To review a pull request, look at all the changes they made.
+Best Practices for PR Contributors:
+GitHub and other Git hosts support adding inline comments, so you can comment on specific areas of the code when necessary. The best place to do this is the "Files Changed" tab of a pull request.
+It is up to them to address every issue that is brought up, and push the changes back to their branch. They should let you know when they've completed everything, and you can check to make sure you're happy with their changes.
+Let's assume you have some commits on branch yourLocalBranch
, and you want to merge them into a branch on your team's GitHub (which uses the default remote alias, origin
) called branchYouWantToMergeTo
.
Part 1 - Set up your branch:
+main
. If you are not on the main
branch, switch to it with git checkout main
git pull origin main
. This will make sure your new branch contains all the most recent changesgit branch joel/changeButtonColor
git checkout joel/changeButtonColor
. Refer to Branches if you make any mistakes.Part 2 - Make your commits:
+git status
frequently to make sure you are doing everything correctly.Part 3 - Push your commits to origin:
+git push origin joel/changeButtonColor
git pull origin main
(or the branch you want to merge to) on your local machine. This will bring up the merge conflict.git add
and git commit
your fixes!git push origin yourLocalBranch
branchYouWantToMergeTo
, and the source should be yourLocalBranch
.Clean up:
+git branch -d yourBranchName
)Now that you understand the complete process on an individual level, let's take a step back to understand how your team will be using git.
+Here is the Git workflow we recommend:
+This is what is used at Microsoft. It works well and it's good practice to teach it.
+fixButtonGlitch
git push
their code to a branch on your origin repo that shares the same namemain
.What should I do if I made a commit in the wrong branch?
+What should I do if I started work in the wrong branch but not committed yet?
+What if I want to revert a commit?
+How do I push code from my local branch to a remote branch that has a different name?
+How do I create a new local branch based on a pre-existing remote branch?
+ +What do I do if my pull request says it has merge conflicts?
+Here are some advanced Git commands you can use to boost your Git game to the next level. They are not essential to using Git, but you may find them helpful. If you're still learning the beginner commands, we recommend focusing on them until you're comfortable with them before worrying about these advanced commands.
+Here are some additional commands and flags for existing commands that you can use while you are staging files and adding commits.
+If you want descriptions of the basic staging and commits, please see staging files & creating commits in the beginner part of the guide.
+git status (-s) (-v)
(-s
) displays information in a shortened and fast format
(-v
) displays information in more detail, with additions such as the textual changes of uncommitted files
git add [fileName or folderName] (-u)
You can use the -u
flag on git add
for the following effects:
(-u
) adds new/modified files and IGNORES deleted files to the staging area
git commit (-a) (-am) "[Commit message here]"
You can use the -a
and -am
flags on git
commit for the following effects:
(-a
) commits all files in the staging area
(-am
) commits all files in the staging area and allows the addition of the commit message in the command
"[Commit message here]"
the message that will be attached to the commit. Only usable if -m
or -am
is used; otherwise, a text editor will appear for the commit message.
Below is the general sequence of commands to check, and undo previous commits. Notice that we must use the commit comments as the easiest factor in differentiating between commits. It is important to use a descriptive comment for each commit.
+git log
Displays old commits with the ID hash and commit comment on the current branch.
+git checkout [id hash]
Will make your working directory match the exact state of the id’ed commit.
+Nothing you do here will be saved to the current state of the project (to go back do git checkout main
).
git clean (-f) (-n)
git clean -n shows which UNTRACKED files will be removed, should you do git clean -f.
+Good practice is to always -n
before you -f
. Learn more
(-n
) runs a dry run (previews what files would be removed).
(-f
) to force untracked file detection (removes the files).
git revert
Undoes a single commit.
+git reset [id hash]
Goes back to the specified commit by removing all subsequent commits.
+git merge [branchName]
Merges the specified branch into the branch that your local directory is currently on. +In a typical workflow, you will not need to use this command ever. +Instead, git pull and pull requests will handle all merging for you.
+Check out this video as a crash course to React:
+https://www.youtube.com/watch ?v=Ke90Tje7VS0
+If you find this video confusing, or prefer a different one as a React intro, please let us know :)
+If you prefer reading to watching videos, this guide is helpful:
+React is built around the concept of components. Components are reusable, self-contained units that encapsulate the UI and behavior of a part of the application. React applications are typically composed of many components.
+function MyComponent() {
+ return <div>Hello, World!</div>;
+}
+
+JSX (JavaScript XML) is a syntax extension for JavaScript that allows you to write HTML-like code within your JavaScript. It's used in React to define the structure of components.
+const element = <h1>Hello, world!</h1>;
+
+React renders components into the DOM (Document Object Model). You can use the ReactDOM
library to render a component into a specific HTML element.
ReactDOM.render(<MyComponent />, document.getElementById('root'));
+
+Props (short for properties) allow you to pass data from a parent component to a child component. This enables you to create dynamic and reusable components.
+function Greeting(props) {
+ return <div>Hello, {props.name}</div>;
+}
+
+State is a way to store and manage data that can change over time. It is used to make components dynamic and interactive.
+class Counter extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = { count: 0 };
+ }
+}
+
+React components have a lifecycle, and you can use lifecycle methods to perform actions at various stages of a component's existence. For example, componentDidMount
is called after a component is rendered.
componentDidMount() {
+ // Perform initialization after rendering.
+}
+
+You can define event handlers in React components to respond to user interactions, such as clicks or input changes.
+function Button() {
+ function handleClick() {
+ console.log('Button clicked');
+ }
+
+ return <button onClick={handleClick}>Click me</button>;
+}
+
+You can use conditional statements and expressions to conditionally render different parts of a component based on certain conditions.
+function Greeting(props) {
+ if (props.isLoggedIn) {
+ return <div>Welcome, User!</div>;
+ } else {
+ return <div>Please log in.</div>;
+ }
+}
+
+React provides a way to render lists of elements efficiently and assigns unique keys to each item in the list for optimization.
+const numbers = [1, 2, 3, 4, 5];
+const listItems = numbers.map((number) => <li key={number}>{number}</li>);
+
+React utilizes several JavaScript features and concepts like arrow functions, classes, callbacks, promises, and async/await to create dynamic and interactive user interfaces. Let's explore each of these in detail and discuss how they are related and integrated in React:
+Arrow functions, classes, callbacks, promises, and async/await are fundamental JavaScript concepts that are commonly used in React. Let's explore each of these topics and how they are related and integrated in React:
+Arrow functions are a concise way to write functions in JavaScript. They are commonly used in React for defining components and functions, as they have a more compact syntax compared to traditional function expressions. Arrow functions capture the this
value of the enclosing context automatically, making them suitable for working within React components and event handlers.
Example of an arrow function defining a React component:
+const MyComponent = () => {
+ return <div>Hello, World!</div>;
+};
+
+Classes in JavaScript are used to define and create objects with methods and properties. In React, components are often defined as classes, especially when they need to manage component state and lifecycle methods. React class components extend the React.Component
class and can have methods like render
, componentDidMount
, and more for handling component behavior.
Example of a React class component:
+class MyComponent extends React.Component {
+ render() {
+ return <div>Hello, World!</div>;
+ }
+}
+
+**Note on functional versus class-based components**
When React was first created, class-based components were the standard. But functional components were introduced later, and they eclipse class-based components in every way.
+Our advice: Ironically, you should probably never use class-based components!
+Stick to functional components. They are more modern and more versatile.
+Lots of tutorial content online still uses class-based components. If you stumble upon a tutorial or explanation that uses a class-based component, and you're new to React, please search for a functional-component alternative instead!
+Callbacks are functions that are passed as arguments to other functions and are executed at a later time or in response to an event. React uses callbacks extensively, especially in event handling. For example, you can pass callback functions to event handlers to respond to user interactions.
+Example of a callback function for handling a button click:
+function handleClick() {
+ console.log('Button clicked');
+}
+
+<button onClick={handleClick}>Click me</button>
+
+Promises are a way to handle asynchronous operations in JavaScript. They represent a value that might be available now, or in the future, or never. Promises have three states: pending
, fulfilled
, and rejected
.
Creating Promises:
+You can create a promise using the Promise
constructor. It takes a function with two arguments: resolve
and reject
. You typically perform an asynchronous operation in this function and call resolve
when the operation is successful or reject
when it fails.
const myPromise = new Promise((resolve, reject) => {
+ // Asynchronous operation
+ if (operationSucceeded) {
+ resolve(result);
+ } else {
+ reject(error);
+ }
+});
+
+Chaining Promises:
+Promises can be chained together using .then()
and .catch()
to handle the resolved value or errors. This chaining allows you to compose complex asynchronous operations.
myPromise
+ .then((result) => {
+ // Handle success
+ })
+ .catch((error) => {
+ // Handle error
+ });
+
+async/await
: async
and await
are modern JavaScript features for working with asynchronous code. They make asynchronous code more readable and maintainable.
async
Function:
+An async
function is a function that always returns a promise. It allows you to use the await
keyword inside the function to pause execution until the promise is resolved.
async function fetchData() {
+ const data = await fetch('https://api.example.com/data');
+ return data.json();
+}
+
+await
Keyword:
+The await
keyword can only be used inside an async
function. It pauses the execution of the function until the promise is resolved, and it returns the resolved value.
const result = await myPromise;
+// The code here will not execute until myPromise is resolved.
+
+React applications often involve asynchronous operations, such as fetching data from APIs or making network requests. Promises, async/await
, and React's lifecycle methods can be integrated for managing asynchronous tasks effectively:
Fetching Data:
+You can use async/await
to fetch data in React components. Typically, you do this inside componentDidMount()
or within functional components using the useEffect
hook.
async componentDidMount() {
+ try {
+ const response = await fetch('https://api.example.com/data');
+ const data = await response.json();
+ this.setState({ data });
+ } catch (error) {
+ console.error('Error fetching data:', error);
+ }
+}
+
+Updating Component State: +Once the data is fetched, you can update the component state to trigger a re-render with the new data.
+Handling Errors:
+Use try/catch
to handle errors gracefully. You can also integrate error boundaries in React to catch errors in the component tree.
Using Promises:
+React works well with Promises, and you can use .then()
and .catch()
to manage asynchronous operations. However, async/await
is often preferred for its more readable and synchronous-like syntax.
Integrating Promises and async/await
in React allows you to manage asynchronous operations in a clean and structured way, providing a better user experience by preventing UI blocking during data retrieval.
In React, events are used to capture and respond to user interactions, such as clicks, input changes, and mouse movements. Event handling in React is similar to handling events in traditional HTML, but there are some differences due to React's synthetic event system.
+In React, you define event handlers as functions and attach them to JSX elements using event attributes. Here's an example of how you might handle a click event in React:
+function Button() {
+ function handleClick() {
+ console.log('Button clicked');
+ }
+
+ return <button onClick={handleClick}>Click me</button>;
+}
+
+The onClick
attribute specifies the event handler function, handleClick
, which will be executed when the button is clicked. React's synthetic event system provides a consistent API for handling events across different browsers.
In React, event handlers are passed an event object as an argument. This object contains information about the event, such as the type of event, target element, and any event-specific data. You can access event properties and methods within your event handler functions.
+function handleChange(event) {
+ console.log('Input value:', event.target.value);
+}
+
+Higher Order Components are a design pattern in React that allows you to reuse component logic by wrapping one or more components with a higher-order component. HOCs are not a part of the React API; they are a pattern that leverages the composability of components.
+HOCs are functions that take a component and return a new enhanced component. They can add props, modify behavior, or encapsulate certain functionality. For example, you might create an HOC that provides authentication, access control, or data fetching capabilities to a component.
+Here's a simplified example of a higher order component that provides a "loading" indicator to a component:
+function withLoadingIndicator(WrappedComponent) {
+ return function WithLoadingIndicator(props) {
+ if (props.isLoading) {
+ return <div>Loading...</div>;
+ }
+ return <WrappedComponent {...props} />;
+ };
+}
+
+You can use an HOC by wrapping your component with it. For instance, suppose you have a component called MyComponent
, and you want to add a loading indicator using the withLoadingIndicator
HOC:
const MyComponentWithLoading = withLoadingIndicator(MyComponent);
+
+Now, MyComponentWithLoading
is a new component that includes the loading indicator logic from the HOC. You can render it as you would with any other component.
<MyComponentWithLoading isLoading={true} />
+
+HOCs enable you to separate concerns and promote reusability. They help you avoid code duplication by encapsulating common functionality in a separate function. This makes your code more maintainable and flexible, allowing you to compose and extend component behavior as needed.
+Events and HOCs can work together in a React application. For instance, you might create an HOC that handles common event-related logic, such as tracking user interactions, and then wrap components that need that behavior. This can help centralize event handling logic and make it reusable across multiple components. Additionally, you can pass event handling functions as props when composing components with HOCs, allowing for flexible customization of event behavior.
+In summary, events in React are essential for capturing and responding to user interactions, while Higher Order Components are a design pattern that promotes reusability and composability of component logic. You can use HOCs to encapsulate and extend event-related logic, making it easier to manage event handling across your React application.
+Props and state are two fundamental concepts in React, and they play distinct roles in how components work.
+Props (short for properties) are a mechanism for passing data from a parent component to a child component. Props are read-only, meaning that the child component cannot modify the props it receives. They are used to customize or configure child components based on data from their parent.
+Example of using props:
+function Greeting(props) {
+ return <div>Hello, {props.name}</div>;
+}
+
+State is a way to store and manage data that can change over time within a component. State is used to make components dynamic and interactive. Unlike props, state is mutable, and components can change their internal state using the setState
method. State is often used for data that the component needs to keep track of, such as user input or UI state.
Example of using state:
+class Counter extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = { count: 0 };
+ }
+
+ render() {
+ return (
+ <div>
+ <p>Count: {this.state.count}</p>
+ <button onClick={() => this.setState({ count: this.state.count + 1 })}>
+ Increment
+ </button>
+ </div>
+ );
+ }
+}
+
+Props and state are often used together to create dynamic and interactive React applications. Here's how they relate and are integrated:
+Passing Data: Props are used to pass data from a parent component to its child components. This data can be initial data that a child component uses to render itself.
+Updating Data: State is used to manage data that can change within a component. Components can have state and use it to keep track of user interactions, input, or changes in data.
+Reactivity: When a parent component passes props to a child component, any changes to those props in the parent will re-render the child. This allows for dynamic updates.
+State Management: State is local to the component that owns it, and changes in state trigger re-renders of that component, updating the UI as needed.
+Lifting State: Sometimes, you might need to manage state at a higher level in the component tree and pass it down as props to child components. This is called "lifting state up."
+In summary, props are for passing data from parent to child, while state is for managing data that can change within a component. Together, they enable you to build interactive and data-driven React applications. Hooks, especially the useState
hook, make it easier to manage local state in functional components, further enhancing the capabilities of React functional components.
React introduced Hooks in version 16.8 as a way to add state and side-effects to functional components, which were previously limited to stateless rendering.
+In React, "stateless rendering" refers to the practice of creating functional components (also known as stateless functional components) that are purely responsible for rendering UI based on the input data provided through props. These components do not manage or maintain any internal state.
+Out with the old in with the new KING, hooks allow you to reuse stateful logic and side-effects across components, making functional components more powerful and flexible.
+Some of the most commonly used hooks include:
+useState
This one might sound familiar from above, useState
hook allows functional components to manage local state. It takes an initial state value and returns an array with the current state and a function to update it.
import React, { useState } from 'react';
+
+function Counter() {
+ const [count, setCount] = useState(0);
+
+ return (
+ <div>
+ <p>Count: {count}</p>
+ <button onClick={() => setCount(count + 1)}>Increment</button>
+ </div>
+ );
+}
+
+useEffect
The useEffect
hook enables you to perform side-effects in functional components. It takes a function that will be executed after every render, and you can specify dependencies to control when the effect should run.
import React, { useEffect, useState } from 'react';
+
+function Example() {
+ const [data, setData] = useState([]);
+
+ useEffect(() => {
+ // Fetch data from an API and update the state
+ fetchData().then((result) => setData(result));
+ }, []); // Empty dependency array runs the effect only once
+}
+
+React provides several other built-in hooks, such as useContext
and useReducer
, which allow you to manage context, state transitions, and references in functional components, respectively.
useContext
: Allows you to access the context API within functional components. It's useful for sharing data across the component tree without prop drilling.import React, { useContext } from 'react';
+
+const ThemeContext = React.createContext('light');
+
+function ThemedButton() {
+ const theme = useContext(ThemeContext);
+ return <button className={theme}>Themed Button</button>;
+}
+
+useReducer
: This hook is used for more complex state management and state transitions. It's similar to setState
but offers more control over how state updates occur.import React, { useReducer } from 'react';
+
+const initialState = { count: 0 };
+
+function counterReducer(state, action) {
+ switch (action.type) {
+ case 'increment':
+ return { count: state.count + 1 };
+ case 'decrement':
+ return { count: state.count - 1 };
+ default:
+ return state;
+ }
+}
+
+function Counter() {
+ const [state, dispatch] = useReducer(counterReducer, initialState);
+
+ return (
+ <div>
+ <p>Count: {state.count}</p>
+ <button onClick={() => dispatch({ type: 'increment' })}> Increment</button>
+ <button onClick={() => dispatch({ type: 'decrement' })}> Decrement</button>
+ </div>
+ );
+}
+
+You can create your own custom hooks to encapsulate and share component logic across different components. Custom hooks promote code reuse and maintainability.
+// Custom hook for handling form input state
+import { useState } from 'react';
+
+function useFormInput(initialValue) {
+ const [value, setValue] = useState(initialValue);
+
+ const handleChange = (e) => {
+ setValue(e.target.value);
+ };
+
+ return {
+ value,
+ onChange: handleChange,
+ };
+}
+
+In summary, hooks in React are a way to manage state and side-effects in functional components. They integrate seamlessly with functional components, making it easier to write and maintain complex logic and enabling better code reuse. React's built-in hooks and the ability to create custom hooks provide a powerful toolset for building dynamic and interactive applications.
+Great Resources(videos): https://www.youtube.com/watch?v=Jl4q2cccwf0&ab_channel=TheNetNinja
+Calling APIs is a key part of any React App. It's what enables your app to communicate with the outside world - including, presumably, your backend.
+Here's a helpful tutorial on the best practices for calling APIs in React:
+https://www.youtube.com/watch?v=bYFYF2GnMy8
+There's also a part 2:
+https://www.youtube.com/watch?v=1tfd6ANaNRY
+The best ways to fetch data are using the popular package Axos (https://www.npmjs.com/package/axios) or the vanilla JS _fetch _function (https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
+Once you have parsed the data, you'll probably want to store it in your state somehow (using useState or a redux store).
+It is also good practice to encapsulate your entire API call into a custom hook, and name the hook according to what it does (ex. useFetchPokemonStats). This is also much easier to do if you use a state-management system like Redux, which is described below.
+The methods described above let you call an API immediately upon rendering a certain component. But what happens if you want to manually trigger an API call (ex. after a certain action or event)?
+Your API call should still use useEffect, and should look mostly like the calls you learned about in Part 1. The 1 difference is you need to guard the useEffect wisely in its dependency array.
+As you recall, the dependency array of a useEffect contains everything that the useEffect depends upon - if any of its dependencies change, it will have a _side effect _of rerunning the useEffect.
+So, you can define a specific variable which only changes when you want your API call to run. You can put that variable in the dependency array of the useEffect. When the action or event that you want to trigger the API call occurs, you should change the trigger variable. This change will trigger the useEffect to run. The trigger variable should never change except when you want the useEffect to run.
+I personally like making my trigger variable an object which also contains any subvariables that my API call needs. So for example, if I was coding a call to a search API that included a text query and target price, my trigger object would contain those.
+Here is an example of a very basic React application that calls an API to perform a search with a custom hook and a useEffect guarded by a trigger object as described above: https://github.com/Tech-Start-UCalgary/react-api-examples/tree/main/js-no-redux
+useSWR is a useful React hook for data fetching published by Vercel (creators of Next.js).
+SWR stands for stale-while-revalidate. It allows for smart data fetching and encapsulates a lot of advanced fetching logic (like how often should you refetch? should you have a cache?) in a single line of code.
+You should read more about useSWR here:
+ +You can watch a video tutorial here:
+https://www.youtube.com/watch?v=f7yjEdXgGiM
+React Router is a popular library used for routing in React applications. Routing is the process of determining which UI components should be displayed based on the current URL or path. React Router helps you create single-page applications with multiple views and navigate between them without requiring full page reloads.
+Here's an elaboration on React Router and its integration with React:
+Declarative Routing: React Router uses a declarative approach, where you define the routes and their corresponding components in a clear and organized manner. You specify what component should be rendered when a particular URL is matched.
+Nested Routing: React Router supports nested routes, allowing you to create complex and hierarchical UI structures. This is especially useful for building multi-level menus or complex application layouts.
+Route Parameters: You can define route parameters in your routes, allowing you to extract dynamic data from the URL. For example, a route like /users/:id
can capture the id
as a parameter.
Programmatic Navigation: React Router provides a set of functions for programmatic navigation. You can change the route, push to the browser's history, or replace the current route using these functions. This is useful for actions like form submissions or after successful authentication.
+Route Guards: React Router allows you to implement route guards for protecting routes based on user authentication or other conditions. This ensures that users can only access certain routes if they meet specific criteria.
+React Router is typically integrated into a React application as a separate library. Here's how it's commonly done:
+Installation: You start by installing React Router as a package in your React project. You can use either react-router-dom
(for web applications) or react-router-native
(for mobile applications).
npm install react-router-dom
+
+Router Component: You wrap your entire application (or a part of it) with a <BrowserRouter>
or <HashRouter>
component provided by React Router. This component manages the application's navigation state and listens to changes in the URL.
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
+
+function App() {
+ return (
+ <Router>
+ {/* Define your routes here */}
+ </Router>
+ );
+}
+
+Route Configuration: Inside the <Router>
, you define your routes using the <Route>
component. Each <Route>
component specifies a path and the component to render when the path matches.
<Route path="/home" component={Home} />
+<Route path="/about" component={About} />
+
+Route Navigation: To navigate between routes, you use the <Link>
component to create links or the history
object to programmatically navigate.
<Link to="/home">Home</Link>
+// OR
+history.push('/home');
+
+Route Parameters: You can use route parameters to capture dynamic values from the URL. These parameters are accessible as props in the routed components.
+<Route path="/user/:id" component={UserProfile} />
+
+Nested Routes: You can nest routes by defining routes within the components rendered by other routes. This allows for hierarchical routing structures.
+<Route path="/dashboard" component={Dashboard}>
+ <Route path="/dashboard/profile" component={Profile} />
+</Route>
+
+By integrating React Router into your React application, you can create well-organized, client-side routing that provides a seamless and efficient user experience for navigating different parts of your application.
+Redux is a widely used state container for javascript apps. As soon as your app reaches any level of data complexity, it makes a ton of sense to start using Redux to manage your state.
+A fair warning: Redux will seem complicated at the beginning. That's completely expected! Push through that initial discomfort and you'll get used to it in no time :)
+Here is a great introductory video to React-Redux:
+https://www.youtube.com/watch?v=CVpUuw9XSjY
+I highly recommend using **createSlice to setup your Redux Store. **It is a simple way to encapsulate creating actions and slicers in a simple, easy-to-read, easy-to-understand way. Here is a short video that does a great job explaining how to use createSlice:
+https://www.youtube.com/watch?v=e0MEtFaQTZk
+To access your Redux state and update your Redux state in React, I highly recommend using the twin hooks **useSelector **and useDispatch respectively. They are simple, easy, and elegant.
+https://www.youtube.com/watch?v=3zoIigieur0
+Next.js is a framework built on top of React, designed to simplify and enhance the development of web applications. It provides several features and benefits while seamlessly integrating with React. Let's explore these aspects interactively:
+Q1: What is Next.js?
+Next.js is a framework for building web applications that are built on top of the React library. It simplifies many aspects of React development and adds capabilities for server-side rendering, routing, and more.
+Q2: How does Next.js relate to React?
+Next.js is an extension of React. It leverages React's component-based structure and allows you to build React applications while providing additional tools and features for server-side rendering, routing, and other optimizations.
+Q3: What are some key features of Next.js?
+Next.js offers several key features:
+Server-Side Rendering (SSR): Next.js enables server-side rendering, which improves performance and SEO by rendering pages on the server before sending them to the client.
+Routing: It includes a built-in routing system, so you can easily define and navigate between pages.
+File-Based Routing: Routes are created based on the file structure, making it intuitive and easy to organize your application.
+Automatic Code Splitting: It automatically splits your JavaScript code into smaller, more manageable chunks, optimizing loading times.
+Static Site Generation (SSG): Next.js allows you to generate static HTML files at build time for even better performance and SEO.
+Q4: How do you create a new Next.js app?
+To create a new Next.js app, you can use the following commands:
+npx create-next-app my-nextjs-app
+cd my-nextjs-app
+npm run dev
+
+This will set up a new Next.js application and start the development server.
+Q5: Can you explain the pages and routing in Next.js?
+In Next.js, you create pages by simply adding files to the pages
directory. Each file becomes a route. For example, if you create pages/about.js
, you will have a route at /about
.
Q6: How does Next.js handle data fetching?
+Next.js allows you to fetch data during server-side rendering using the getServerSideProps
function. This data can be injected into your React components as props.
export async function getServerSideProps() {
+ // Fetch data from an API or database
+ const data = await fetchData();
+
+ return {
+ props: { data },
+ };
+}
+
+Q7: What's the advantage of server-side rendering in Next.js?
+Server-side rendering in Next.js improves the initial loading speed of your application and helps with search engine optimization (SEO). It also ensures that users see content more quickly.
+Q8: How can I build a static website with Next.js?
+Next.js provides static site generation (SSG) via the getStaticProps
function. You can generate static HTML files for your pages at build time.
export async function getStaticProps() {
+ // Fetch data from an API or database
+ const data = await fetchData();
+
+ return {
+ props: { data },
+ };
+}
+
+Q9: Are there any limitations or trade-offs with Next.js?
+While Next.js offers many advantages, it may introduce complexity to smaller projects. It requires server-side rendering, which might not be necessary for all applications.
+Q10: Can I deploy Next.js applications to various hosting platforms?
+Yes, you can deploy Next.js applications to a wide range of hosting platforms, including Vercel, Netlify, and AWS. These platforms often provide built-in support for Next.js, making deployment straightforward.
+Next.js is a powerful tool that enhances React applications by providing features like server-side rendering, routing, and automatic code splitting. It simplifies the development process and improves performance. If you have more specific questions or need further information about Next.js, feel free to ask!
+ +Please get aquanted with our React Guide before you read this page, this is just a reccomendation though. Transitioning from a good background in React to React Native is a relatively smooth process, as many concepts carry over. However, there are specific topics and components you should learn to effectively work with React Native. Here's an outline of the topics you need to cover:
+These tutorials should be suffecient to get started but this guide give many more subtle topics that are not covered in these videos. Choose your weapon wisely.
+Components in React Native are similar to those in React, but with some variations and additional elements. Here's a more detailed breakdown:
+React Native provides a set of core components that are similar to HTML elements. These include:
+View
: The fundamental component for creating UI layouts.Text
: Used for displaying text.Image
: For displaying images.ScrollView
: For scrollable content.TextInput
: For text input fields.You can create your custom components just like in React. These components can be stateless functional components or class components. To create a custom component, use the View
, Text
, Image
, and other core components to compose your UI.
Styling in React Native is different from traditional web development. You have various options for styling your components:
+React Native supports inline styles using JavaScript objects. You can apply styles directly to components, like this:
+<View style={{ flex: 1, backgroundColor: 'lightblue' }}>
+ <Text style={{ fontSize: 20, color: 'black' }}>Hello, React Native!</Text>
+</View>
+
+Using stylesheets, you can create reusable style definitions:
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: 'lightblue',
+ },
+ text: {
+ fontSize: 20,
+ color: 'black',
+ },
+});
+
+<View style={styles.container}>
+ <Text style={styles.text}>Hello, React Native!</Text>
+</View>
+
+React Native relies heavily on flexbox for layout design. It's similar to CSS flexbox but with a few differences. You can use properties like flex
, alignItems
, and justifyContent
to control layout.
<View style={{ flex: 1, flexDirection: 'column', justifyContent: 'center', alignItems: 'center' }}>
+ <Text>Hello, React Native!</Text>
+</View>
+
+Understanding layout is vital in React Native to create responsive and visually appealing designs.
+Flexbox Layout: Flexbox is the primary layout system in React Native. It allows you to design flexible and adaptive layouts. Key properties include:
+flex
: Determines how space is distributed among children.alignItems
: Aligns items along the cross-axis (vertical alignment).justifyContent
: Aligns items along the main axis (horizontal alignment).flexDirection
: Sets the direction of the main axis.Positioning: You can control the position of elements using properties like position
, top
, left
, right
, and bottom
.
Dimensions: Set dimensions using width
and height
. You can use percentages, fixed values, or dynamic values like flex
.
Responsive Design: React Native allows you to create responsive designs using Dimensions
and the onLayout
event.
Orientation Handling: Handle changes in device orientation by adjusting your layout accordingly. Use the Dimensions
API to detect changes.
Stylesheet Composition: Compose styles using stylesheets and conditionally apply styles based on screen dimensions or other criteria.
+Best Practices:
+Separation of Concerns: Keep styles, logic, and presentation separate for better maintainability and code clarity.
+Optimizing Styles: Optimize styles to reduce unnecessary re-renders and improve app performance.
+By mastering these concepts related to components, styling, and layout in React Native, you can create rich and visually appealing mobile app user interfaces. Flexbox, in particular, is a powerful tool for creating flexible layouts, and understanding the nuances of styling is crucial for developing a professional-looking app.
+Navigation is a crucial aspect of building mobile applications with React Native. It involves creating the structure and flow of your app, allowing users to move between different screens or views. The most common library for implementing navigation in React Native is React Navigation. Here's a more detailed overview of navigation in React Native:
+1. Installing React Navigation:
+npm install @react-navigation/native @react-navigation/stack
+
+2. Stack Navigator:
+import { createStackNavigator } from '@react-navigation/stack';
+
+const Stack = createStackNavigator();
+
+3. Defining Screens:
+function HomeScreen() {
+ // Your screen's content
+}
+
+function ProfileScreen() {
+ // Your screen's content
+}
+
+4. Navigating Between Screens:
+import { NavigationContainer } from '@react-navigation/native';
+import { createStackNavigator } from '@react-navigation/stack';
+
+const Stack = createStackNavigator();
+
+function App() {
+ return (
+ <NavigationContainer>
+ <Stack.Navigator>
+ <Stack.Screen name="Home" component={HomeScreen} />
+ <Stack.Screen name="Profile" component={ProfileScreen} />
+ </Stack.Navigator>
+ </NavigationContainer>
+ );
+}
+
+In your HomeScreen component, you can use navigation.navigate('Profile')
to navigate to the ProfileScreen.5. Passing Data Between Screens:
+// In HomeScreen
+navigation.navigate('Profile', { userId: 123 });
+
+// In ProfileScreen
+const userId = route.params.userId;
+
+6. Drawer Navigation and Tab Navigation:
+7. Nested Navigation:
+React Navigation allows you to nest navigators within each other, creating complex navigation structures. This can be useful when you have a tab navigator and want to use a stack navigator within one of the tabs, or if you want to combine different types of navigators for more intricate navigation patterns.
+Here's an example of nesting a Stack Navigator within a Tab Navigator:
+import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
+import { createStackNavigator } from '@react-navigation/stack';
+
+const Tab = createBottomTabNavigator();
+const Stack = createStackNavigator();
+
+// Define a tab navigator with a stack navigator in one of the tabs
+function TabNavigator() {
+ return (
+ <Tab.Navigator>
+ <Tab.Screen name="Tab1" component={Tab1Component} />
+ <Tab.Screen name="Tab2" component={Tab2Component} />
+ <Tab.Screen name="Tab3" component={StackScreen} />
+ </Tab.Navigator>
+ );
+}
+
+// Define a stack navigator to use within a tab
+function StackScreen() {
+ return (
+ <Stack.Navigator>
+ <Stack.Screen name="StackScreen1" component={StackScreen1Component} />
+ <Stack.Screen name="StackScreen2" component={StackScreen2Component} />
+ </Stack.Navigator>
+ );
+}
+
+8. Navigation Lifecycle:
+React Navigation provides navigation lifecycle events that allow you to perform actions when a screen comes into view or goes out of view. Common lifecycle events include:
+focus
: Triggered when a screen comes into focus.blur
: Triggered when a screen loses focus.didFocus
: Triggered after the screen has come into focus.You can add listeners to these events to perform actions or fetch data when a screen is in focus.
+import { useFocusEffect } from '@react-navigation/native';
+
+function MyScreen({ navigation }) {
+ // Add a focus event listener
+ useFocusEffect(
+ React.useCallback(() => {
+ // Perform actions when the screen comes into focus
+ console.log('Screen is in focus');
+ // You can also fetch data or make API calls here
+ }, [])
+ );
+
+ // ... rest of the screen component
+}
+
+9. Screen Options:
+You can customize the appearance and behavior of each screen's navigation using the options
property in your screen component. This allows you to set options like the screen title, header style, and more.
function MyScreen({ route, navigation }) {
+ // Define screen-specific options
+ React.useLayoutEffect(() => {
+ navigation.setOptions({
+ title: 'Custom Title',
+ headerStyle: {
+ backgroundColor: 'blue',
+ },
+ headerTintColor: 'white',
+ });
+ }, [navigation]);
+
+ // ... rest of the screen component
+}
+
+10. Navigation Methods:
+React Navigation provides a set of methods that allow you to navigate between screens programmatically. Common methods include:
+navigate
: Navigate to a new screen in the same stack.push
: Push a new screen onto the stack.pop
: Pop the current screen from the stack.goBack
: Navigate back to the previous screen.These methods are accessible through the navigation
prop in your screen components.
function MyScreen({ navigation }) {
+ return (
+ <View>
+ <Button title="Go to Screen2" onPress={() => navigation.navigate('Screen2')} />
+ <Button title="Push Screen3" onPress={() => navigation.push('Screen3')} />
+ <Button title="Go Back" onPress={() => navigation.goBack()} />
+ </View>
+ );
+}
+
+These features offer extensive flexibility in designing complex navigation structures and allow you to respond to navigation events and customize screen-specific options. Understanding these concepts is crucial for building intuitive and feature-rich navigation in your React Native applications.
+Platform-specific code in React Native involves writing code that is specific to either iOS or Android platforms. This is sometimes necessary when you want to implement platform-specific features, handle platform-specific behaviors, or optimize your app for a particular platform. Here's a more detailed overview of this topic:
+1. Platform-Specific Components and Styling:
+React Native allows you to conditionally render components or apply styles based on the platform. For example, you can use the Platform.OS
property to determine the platform:
import { View, Text } from 'react-native';
+import { Platform } from 'react-native';
+
+const MyComponent = () => (
+ <View>
+ <Text>Common Text</Text>
+ {Platform.OS === 'ios' && <Text>iOS only Text</Text>}
+ {Platform.OS === 'android' && <Text>Android only Text</Text>}
+ </View>
+);
+
+Similarly, you can conditionally apply styles:
+import { StyleSheet } from 'react-native';
+
+const styles = StyleSheet.create({
+ commonStyle: {
+ // Common styles
+ },
+ iosStyle: {
+ // iOS-specific styles
+ },
+ androidStyle: {
+ // Android-specific styles
+ },
+});
+
+const MyComponent = () => (
+ <View>
+ <Text style={[styles.commonStyle, Platform.OS === 'ios' ? styles.iosStyle : styles.androidStyle]}>
+ Platform-specific styling
+ </Text>
+ </View>
+);
+
+2. Platform-Specific Modules:
+In some cases, you might need to use platform-specific modules or APIs. React Native provides a way to do this using the .ios.js
and .android.js
file extensions. For example, you can have separate implementations for iOS and Android as follows:
MyModule.ios.js
for iOS-specific code.MyModule.android.js
for Android-specific code.React Native will automatically pick the right file based on the platform. This is useful when dealing with platform-specific features or APIs.
+3. Conditional Logic:
+You can use conditional logic to handle platform-specific behaviors. For instance, you might need to request permissions differently on iOS and Android or use platform-specific libraries.
+import { PermissionsAndroid, Platform } from 'react-native';
+
+async function requestLocationPermission() {
+ if (Platform.OS === 'android') {
+ // Android-specific logic for requesting permissions
+ try {
+ const granted = await PermissionsAndroid.request(
+ PermissionsAndroid.PERMISSIONS.ACCESS_FINE_LOCATION,
+ );
+ if (granted === PermissionsAndroid.RESULTS.GRANTED) {
+ console.log('Location permission granted.');
+ } else {
+ console.log('Location permission denied.');
+ }
+ } catch (err) {
+ console.warn(err);
+ }
+ } else if (Platform.OS === 'ios') {
+ // iOS-specific logic for requesting permissions
+ // ...
+ }
+}
+
+4. Platform-Specific Libraries:
+There are times when you need to use platform-specific libraries or modules. React Native allows you to conditionally include these libraries based on the platform. You can use conditional require
statements to achieve this:
let platformSpecificLibrary;
+if (Platform.OS === 'ios') {
+ platformSpecificLibrary = require('ios-specific-library');
+} else {
+ platformSpecificLibrary = require('android-specific-library');
+}
+
+5. Native Modules:
+Understanding how to handle platform-specific code is important for ensuring your React Native app functions correctly and efficiently on both iOS and Android devices. By using these techniques, you can create a seamless and native-like experience for users on each platform.
+Accessing device features in React Native involves interacting with native device functionality, such as the camera, geolocation, sensors, and more. Here, I'll provide more detail on this topic and examples of how to access specific device features:
+Camera:
+react-native-camera
library. This library allows you to capture photos and record videos. You can also customize the camera settings, switch between front and back cameras, and apply real-time image processing.import { RNCamera } from 'react-native-camera';
+
+// In your component
+<RNCamera
+ type={RNCamera.Constants.Type.back}
+ flashMode={RNCamera.Constants.FlashMode.auto}
+/>
+
+Geolocation:
+Geolocation
module in React Native. It provides methods for retrieving the user's current location and monitoring changes in real-time.import Geolocation from '@react-native-community/geolocation';
+
+// Get the current location
+Geolocation.getCurrentPosition((position) => {
+ console.log(position.coords.latitude, position.coords.longitude);
+});
+
+Sensors:
+react-native-sensors
library. You can use this library to collect data from these sensors.import { Accelerometer } from 'react-native-sensors';
+
+const accelerometerObservable = new Accelerometer();
+
+const subscription = accelerometerObservable.subscribe((data) => {
+ console.log('Acceleration X:', data.x);
+ console.log('Acceleration Y:', data.y);
+ console.log('Acceleration Z:', data.z);
+});
+
+Contacts:
+react-native-contacts
library. This allows you to read and write contacts to the user's address book.import Contacts from 'react-native-contacts';
+
+// Fetch all contacts
+Contacts.getAll()
+ .then((contacts) => {
+ console.log(contacts);
+ })
+ .catch((error) => {
+ console.error(error);
+ });
+
+Device Information:
+react-native-device-info
library. You can retrieve details like the device's manufacturer, model, unique identifier, and more.import DeviceInfo from 'react-native-device-info';
+
+// Get device information
+console.log('Device Model:', DeviceInfo.getModel());
+console.log('Device ID:', DeviceInfo.getUniqueId());
+
+Bluetooth and NFC:
+react-native-ble-manager
and react-native-nfc-manager
. These libraries enable communication with nearby devices and NFC tags.When accessing device features in React Native, it's essential to follow the documentation and best practices for the specific libraries and modules you're using. Additionally, consider handling permissions appropriately, especially for features like camera, geolocation, and contacts, which may require user consent.
+Native modules and bridges in React Native are a way to access native code (Java or Objective-C) from JavaScript and vice versa. They are essential for tasks that require platform-specific functionality or performance optimization. Let's dive into more detail and provide examples of how to create and use native modules and bridges in React Native.
+Native modules allow you to expose native code to JavaScript in a structured manner. Here's how to create a simple native module:
+Create a Native Module for iOS (Objective-C):
+Let's say you want to create a native module that shows a native iOS alert.
+// AlertModule.h
+#import <React/RCTBridgeModule.h>
+
+@interface AlertModule : NSObject <RCTBridgeModule>
+@end
+
+// AlertModule.m
+#import "AlertModule.h"
+#import <React/RCTLog.h>
+
+@implementation AlertModule
+
+RCT_EXPORT_MODULE();
+
+RCT_EXPORT_METHOD(showAlert:(NSString *)title message:(NSString *)message)
+{
+ UIAlertController *alert = [UIAlertController
+ alertControllerWithTitle:title
+ message:message
+ preferredStyle:UIAlertControllerStyleAlert];
+
+ UIAlertAction *ok = [UIAlertAction
+ actionWithTitle:@"OK"
+ style:UIAlertActionStyleDefault
+ handler:nil];
+
+ [alert addAction:ok];
+
+ UIViewController *rootViewController = [[[[UIApplication sharedApplication] delegate] window] rootViewController];
+ [rootViewController presentViewController:alert animated:YES completion:nil];
+}
+
+@end
+
+Create a Native Module for Android (Java):
+To do the same thing in Android, create a native module to show an alert dialog.
+// AlertModule.java
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+
+public class AlertModule extends ReactContextBaseJavaModule {
+ public AlertModule(ReactApplicationContext reactContext) {
+ super(reactContext);
+ }
+
+ @Override
+ public String getName() {
+ return "AlertModule";
+ }
+
+ @ReactMethod
+ public void showAlert(String title, String message) {
+ AlertDialog.Builder builder = new AlertDialog.Builder(getCurrentActivity());
+ builder.setTitle(title);
+ builder.setMessage(message);
+ builder.setPositiveButton("OK", null);
+ builder.show();
+ }
+}
+
+Using Native Modules in JavaScript:
+In your JavaScript code, you can now use the native module you created:
+import { NativeModules } from 'react-native';
+
+// For iOS
+NativeModules.AlertModule.showAlert('Hello', 'This is an alert!');
+
+// For Android
+NativeModules.AlertModule.showAlert('Hello', 'This is an alert!');
+
+Bridges in React Native are responsible for connecting JavaScript and native code. React Native's native modules use bridges to enable communication between the two sides. In the examples above, the React Native framework handles the bridge for you.
+Behind the scenes, React Native's bridge system serializes and deserializes data and manages the communication between JavaScript and native modules. It abstracts away many of the complexities, making it easier for developers to work with native modules in a JavaScript-friendly way.
+By using native modules and bridges, you can incorporate platform-specific functionality into your React Native app while maintaining a unified JavaScript codebase. This is particularly helpful when you need to integrate with device-specific features, third-party libraries, or optimize performance.
+Here are some tutorials that dive super in depth for creating a calender native module for Android or IOS.
+let's dive into more detail on state management in React Native and provide examples. State management is crucial for handling the data and UI state in your mobile applications. There are various options for managing state in React Native, similar to React for the web, including React's built-in state management, the Context API, and external libraries like Redux or MobX. Below, we'll cover these options and provide examples for better understanding:
+React Native, like React, allows you to manage state locally within a component using the useState
hook.
Example:
+import React, { useState } from 'react';
+import { View, Text, Button } from 'react-native';
+
+function Counter() {
+ const [count, setCount] = useState(0);
+
+ const increment = () => setCount(count + 1);
+ const decrement = () => setCount(count - 1);
+
+ return (
+ <View>
+ <Text>Count: {count}</Text>
+ <Button title="Increment" onPress={increment} />
+ <Button title="Decrement" onPress={decrement} />
+ </View>
+ );
+}
+
+In this example, the useState
hook is used to manage the count
state variable within the Counter
component.
The Context API allows you to manage global state that can be accessed by multiple components without having to pass props down through the component tree.
+Example:
+import React, { createContext, useContext, useState } from 'react';
+import { View, Text, Button } from 'react-native';
+
+const CountContext = createContext();
+
+function Counter() {
+ const [count, setCount] = useContext(CountContext);
+
+ const increment = () => setCount(count + 1);
+ const decrement = () => setCount(count - 1);
+
+ return (
+ <View>
+ <Text>Count: {count}</Text>
+ <Button title="Increment" onPress={increment} />
+ <Button title="Decrement" onPress={decrement} />
+ </View>
+ );
+}
+
+function App() {
+ const [count, setCount] = useState(0);
+
+ return (
+ <CountContext.Provider value={[count, setCount]}>
+ <View>
+ <Text>My App</Text>
+ <Counter />
+ </View>
+ </CountContext.Provider>
+ );
+}
+
+In this example, the CountContext
is created and used to share the count
state between the Counter
component and the App
component.
Redux is a popular external state management library for React Native. It provides a central store for managing application state and allows for predictable state updates using actions and reducers.
+Example:
+To use Redux in React Native, you need to set up a store, actions, and reducers. Here's a simplified example:
+// Define actions
+const increment = () => ({ type: 'INCREMENT' });
+const decrement = () => ({ type: 'DECREMENT' });
+
+// Define a reducer
+const counterReducer = (state = 0, action) => {
+ switch (action.type) {
+ case 'INCREMENT':
+ return state + 1;
+ case 'DECREMENT':
+ return state - 1;
+ default:
+ return state;
+ }
+};
+
+// Create the Redux store
+import { createStore } from 'redux';
+const store = createStore(counterReducer);
+
+// Connect components to the store
+import { connect } from 'react-redux';
+
+function Counter({ count, increment, decrement }) {
+ return (
+ <View>
+ <Text>Count: {count}</Text>
+ <Button title="Increment" onPress={increment} />
+ <Button title="Decrement" onPress={decrement} />
+ </View>
+ );
+}
+
+const mapStateToProps = (state) => ({ count: state });
+const mapDispatchToProps = { increment, decrement };
+
+const ConnectedCounter = connect(mapStateToProps, mapDispatchToProps)(Counter);
+
+This example demonstrates a basic setup of Redux in React Native. It involves defining actions, a reducer, creating the store, and connecting a component to the store.
+The choice of state management in your React Native project depends on the complexity and scalability of your application. React's built-in state management and the Context API are great for simple state needs, while Redux or MobX are more suitable for larger, complex applications with extensive state management requirements.
+AsyncStorage is a crucial concept in React Native, allowing you to store data locally on the user's device. It's similar to the localStorage
in web development but tailored for mobile applications. AsyncStorage is often used to store user preferences, app settings, or any data that needs to persist across app sessions. Here, I'll dive into more detail about AsyncStorage and provide some examples.
Importing AsyncStorage: +To use AsyncStorage, you need to import it from 'react-native':
+import { AsyncStorage } from 'react-native';
+
+Storing Data:
+You can store data in AsyncStorage by using the setItem
method. Here's an example of how to store a simple string:
AsyncStorage.setItem('username', 'JohnDoe')
+ .then(() => {
+ console.log('Data stored successfully');
+ })
+ .catch((error) => {
+ console.error('Error storing data: ', error);
+ });
+
+Retrieving Data:
+To retrieve data, you can use the getItem
method:
AsyncStorage.getItem('username')
+ .then((value) => {
+ if (value !== null) {
+ console.log('Retrieved data: ', value);
+ } else {
+ console.log('Data not found');
+ }
+ })
+ .catch((error) => {
+ console.error('Error retrieving data: ', error);
+ });
+
+Updating Data: +You can update stored data by simply setting a new value for the same key:
+AsyncStorage.setItem('username', 'NewUsername')
+ .then(() => {
+ console.log('Data updated successfully');
+ })
+ .catch((error) => {
+ console.error('Error updating data: ', error);
+ });
+
+Deleting Data:
+To remove data from AsyncStorage, use the removeItem
method:
AsyncStorage.removeItem('username')
+ .then(() => {
+ console.log('Data removed successfully');
+ })
+ .catch((error) => {
+ console.error('Error removing data: ', error);
+ });
+
+Handling Errors:
+It's essential to handle errors, as reading from or writing to AsyncStorage may fail due to various reasons, such as storage limitations or permissions. Always use try...catch
or promise-based error handling to ensure your app gracefully handles errors.
Working with JSON Data: +AsyncStorage stores data as strings, so if you need to store complex data structures like objects or arrays, you should serialize them to JSON when storing and parse them when retrieving:
+const user = {
+ name: 'John Doe',
+ email: 'john@example.com',
+};
+
+AsyncStorage.setItem('user', JSON.stringify(user))
+ .then(() => {
+ console.log('User data stored successfully');
+ })
+ .catch((error) => {
+ console.error('Error storing user data: ', error);
+ });
+
+// Retrieving and parsing the user data
+AsyncStorage.getItem('user')
+ .then((value) => {
+ if (value !== null) {
+ const userData = JSON.parse(value);
+ console.log('Retrieved user data: ', userData);
+ } else {
+ console.log('User data not found');
+ }
+ })
+ .catch((error) => {
+ console.error('Error retrieving user data: ', error);
+ });
+
+Remember that AsyncStorage is a simple key-value store and should be used for relatively small amounts of data. For larger datasets, consider using a more robust storage solution or a database. Additionally, be mindful of security considerations when storing sensitive information and ensure that you have the necessary permissions to access AsyncStorage on the user's device.
+Making network requests in React Native is a common task when you need to fetch data from an API or send data to a server. You can use libraries like Axios or the built-in fetch
API to perform these requests. Here, I'll dive into more detail about how to make network requests in React Native using both Axios and fetch
, and provide examples for each:
Axios is a popular library for making HTTP requests. You can use it in your React Native project by following these steps:
+Installation:
+First, you need to install Axios in your project. You can do this with npm or yarn:
+npm install axios
+# or
+yarn add axios
+
+Making a GET Request:
+Here's an example of making a GET request to a remote API using Axios:
+import axios from 'axios';
+
+const fetchUserData = async () => {
+ try {
+ const response = await axios.get('https://api.example.com/users');
+ const userData = response.data;
+ console.log(userData);
+ } catch (error) {
+ console.error('Error fetching user data:', error);
+ }
+};
+
+// Call the function to fetch user data
+fetchUserData();
+
+Making a POST Request:
+To make a POST request with Axios, you can do the following:
+import axios from 'axios';
+
+const sendDataToServer = async (data) => {
+ try {
+ const response = await axios.post('https://api.example.com/postData', data);
+ console.log('Data sent successfully:', response.data);
+ } catch (error) {
+ console.error('Error sending data:', error);
+ }
+};
+
+const dataToSend = {
+ key1: 'value1',
+ key2: 'value2',
+};
+
+// Call the function to send data to the server
+sendDataToServer(dataToSend);
+
+fetch
APIThe fetch
API is a built-in way to make network requests in JavaScript and is available in React Native:
Making a GET Request:
+Here's an example of making a GET request using the fetch
API:
const fetchUserData = () => {
+ fetch('https://api.example.com/users')
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then((userData) => {
+ console.log(userData);
+ })
+ .catch((error) => {
+ console.error('Error fetching user data:', error);
+ });
+};
+
+// Call the function to fetch user data
+fetchUserData();
+
+Making a POST Request:
+Making a POST request with fetch
involves a similar structure:
const sendDataToServer = (data) => {
+ fetch('https://api.example.com/postData', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(data),
+ })
+ .then((response) => {
+ if (!response.ok) {
+ throw new Error('Network response was not ok');
+ }
+ return response.json();
+ })
+ .then((responseData) => {
+ console.log('Data sent successfully:', responseData);
+ })
+ .catch((error) => {
+ console.error('Error sending data:', error);
+ });
+};
+
+const dataToSend = {
+ key1: 'value1',
+ key2: 'value2',
+};
+
+// Call the function to send data to the server
+sendDataToServer(dataToSend);
+
+Both Axios and the fetch
API allow you to make various types of requests (GET, POST, PUT, DELETE, etc.) and handle responses. The choice between the two often comes down to personal preference and specific project requirements. Axios is a popular choice due to its simplicity and ease of use for handling requests and responses.
Third-party integrations in React Native are crucial for adding functionality and features to your app without having to build everything from scratch. Here, I'll provide more detail on some common third-party integrations in React Native along with links to the relevant libraries:
+Push Notifications:
+react-native-firebase
or react-native-push-notification
provide the tools to send and receive push notifications on both iOS and Android.Analytics:
+react-native-firebase/analytics
, react-native-google-analytics
, and react-native-flurry-analytics
enable integration with analytics platforms like Firebase Analytics, Google Analytics, and Flurry.Maps and Location:
+react-native-maps
and react-native-geolocation-service
provide access to Google Maps and geolocation services.Camera and Image Capture:
+react-native-camera
and react-native-image-picker
allow you to access the device's camera and image gallery.Social Media Sharing:
+react-native-share
provide sharing functionality with support for various services.Payment Gateways:
+react-native-in-app-utils
or specific SDKs for payment gateways like Stripe can be integrated.Authentication:
+react-native-firebase/auth
and react-native-auth0
offer easy integration with Firebase Authentication and Auth0, respectively.In-App Messaging:
+react-native-gifted-chat
can be used to quickly add chat functionality.Audio and Video Playback:
+react-native-video
and react-native-sound
provide support for playing audio and video files within your app.AR/VR Integration:
+react-native-arkit
or react-viro
offer AR and VR capabilities.When integrating third-party libraries, make sure to check their documentation for installation and usage instructions, as well as any specific requirements or configurations. Carefully consider your app's requirements and select the libraries that best meet your needs while ensuring they are well-maintained and compatible with your React Native version.
+Security is a critical aspect of any mobile app, including those built with React Native. Here are some security best practices in React Native, along with examples:
+Secure Storage:
+Example:
+// Insecure storage
+const apiKey = 'my-insecure-api-key';
+
+// Secure storage using a library like react-native-secure-storage
+import SecureStorage from 'react-native-secure-storage';
+
+SecureStorage.set('api_key', 'my-secure-api-key');
+
+API Key Management:
+Example:
+// Insecure API key storage
+const apiKey = 'my-insecure-api-key';
+
+// Secure API key storage using environment variables
+const apiKey = process.env.REACT_NATIVE_API_KEY;
+
+Authentication and Authorization:
+Example:
+// Use a secure authentication library like Firebase Authentication or Auth0
+import { Firebase } from 'react-native-firebase';
+
+// Ensure that only authenticated users can access certain features
+if (user.isAuthenticated) {
+ // Display sensitive data or allow certain actions
+}
+
+Network Security:
+Example:
+// Use HTTPS for network requests
+fetch('https://api.example.com/data', {
+ method: 'GET',
+ headers: {
+ 'Content-Type': 'application/json',
+ 'Authorization': 'Bearer ' + user.token,
+ },
+})
+
+Code Obfuscation:
+Secure Communication with Native Modules:
+Example:
+import { NativeModules } from 'react-native';
+
+// Ensure the data passed to a native module is properly sanitized
+const userInput = 'user-input-data';
+NativeModules.MyModule.someMethod(validateInput(userInput));
+
+Input Validation:
+Example:
+// Validate and sanitize user input to prevent XSS
+const userInput = '<script>alert("XSS attack");</script>';
+const sanitizedInput = sanitizeInput(userInput);
+
+Error Handling:
+Example:
+// Handle errors gracefully and do not expose sensitive information to the user
+try {
+ // Code that may throw an error
+} catch (error) {
+ console.error('An error occurred. Please try again later.');
+}
+
+These are essential security best practices for React Native apps, but it's important to note that the specific implementation details may vary depending on your project and the libraries you use. Regularly staying informed about security developments in the React Native ecosystem and taking proactive measures to address vulnerabilities will help ensure the security of your app.
+This guide was meant to be a starting/middle point for learning React Native across its many topics, ranging from front-end to back-end(mainly backe-end because that is what really matters, am I right!). Jokes aside, as you progress through these topics, you'll find that your React experience serves as a strong foundation for learning React Native. React Native allows you to leverage your JavaScript skills to build mobile apps for both iOS and Android, making it a valuable addition to your toolkit.
+ +Want to get into web dev? This guide should be your best friend. It covers some of the basic tools and languages you'll need to dive into the world of web development. Rather than providing tutorials, this guide focuses on directing you towards the best free online content to teach you the fundamentals.
+Our advice:
+This guide was originally developed for Tech Start UCalgary, an undergraduate club for software development and entrepreneurship at the University of Calgary. Check us out here -----> https://linktr.ee/techstartuofc <-----
+Or at our website here ---> https://techstartucalgary.com <-----
+If you're interested in contributing to this guide or in building similar guides for other areas (like Git, project management, or mobile development), please send me an email at joel.happ1@ucalgary.ca
+Good luck on your web dev journey and enjoy the guide!
+HTML is the building block of all webpages. It's ubiquitous throughout application design - everything from websites to mobile apps to desktop apps use HTML as the base for their frontend.
+ +Luckily for you, HTML is also very simple. Don't spend too much time learning it as a beginner - while more advanced HTML concepts do exist, all you need to get started is a basic understanding of how it works.
+To get started, I recommend watching this video and experimenting by building your own HTML document alongside it: https://www.youtube.com/watch?v=UB1O30fR-EE
+To generate a favicon for your site, use this site: https://realfavicongenerator.net/
+No matter which text editor you use (Atom, VSCode, Sublime Text, or something else), I recommend searching for editor plugins to improve your experience writing HTML. Google is your friend here.
+If HTML is the backbone of frontends, CSS is the paint. It's an extremely versatile and powerful way of styling and beautifying your content. CSS is easy to get into, but very difficult to master- if front-end development interests you, I recommend dedicating a significant amount of time towards learning CSS.
+ +To get started, check out this 1 hour introductory video to CSS:
+https://www.youtube.com/watch?v=yfoY53QXEnI
+Another alternative is this free course on Scrimba, which also covers HTML: https://scrimba.com/learn/htmlcss
+One topic that isn't covered in much detail in the previous video is CSS selectors. For most purposes, you'll probably want to keep your selectors simple (using only class names the vast majority of the time). If you want to learn more about advanced selectors, check out this video: https://www.youtube.com/watch?v=Bcr70LIJcOk
+When working on projects with other people, I recommend avoiding element-level selectors, as they can easily screw with work that others are doing.
+Once you have a good grasp of the basics of CSS, one area that I highly recommend learning is CSS Grid. CSS Grid is a fantastic way of organizing and positioning html content, and it comes with loads of features that make it easy to build adaptive web pages. By combining CSS Grid with CSS breakpoints, you can design interfaces that look great on any size of screen, whether it's a big desktop computer or a small mobile phone.
+Highly recommended course for CSS Grid: https://scrimba.com/learn/cssgrid
+(Warning: CSS grid is not supported by some outdated browsers and browsers like Opera Mini which are used mostly in third world countries to save data. If your intended audience includes these people, do not use CSS Grid.)
+How should you organize and refactor your CSS? I recommend using the BEM strategy for your CSS selectors. https://css-tricks.com/bem-101/
+BEM is a particularly helpful methodology to adopt when you're building websites from components like in React, since you can keep the CSS for each component in a separate file. However, it's far from the only strategy for CSS organization, so you can research and adopt others if they suit your needs better.
+Knowing CSS Flexbox is also helpful for arranging the layouts of websites. It's like
+Finally, here is a great video to watch for some simple, powerful tips for writing modern CSS:
+https://www.youtube.com/watch?v=Qhaz36TZG5Y
+JavaScript drives the interactivity and functionality of websites. Using it, you can respond to the user's interactions on your website and you can modify the properties of your HTML dynamically.
+ +To get started with JavaScript, you can watch this playlist: https://www.youtube.com/playlist?list=PLDyQo7g0_nsX8_gZAB8KD1lL4j4halQBJ
+If you're brand new to programming, you should spend more time learning the fundamentals of JavaScript.
+There are a few areas of JavaScript which may be confusing to any newcomers to the language, even if you have previously learned other languages. I recommend practicing and studying to get used to these features.
+Array functions: https://www.youtube.com/watch?v=rRgD1yVwIvE
+_Asynchronous JavaScript (Await, Promises, Callbacks): _https://www.youtube.com/watch?v=_8gHHBlbziw
+_JSON (JavaScript object notation): _https://www.youtube.com/watch?v=wI1CWzNtE-M
+If you encounter another area of JavaScript that gives you troubles let me know and I'll add a section to this guide.
+Here's an introduction to Node.js: JavaScript, but for your operating system instead of your browser. https://www.youtube.com/watch?v=ENrzD9HAZK4 Node.js is frequently used as the backend for the server side of an application or web app.
+Installing Node.js
+We recommend using NVM (node version manager) to install node.js. It allows you to install, uninstall, and switch between different versions of node.js very quickly. Often, you'll need to switch between different versions of node for different projects, so you'll save time by using nvm from the start.
+NVM (Mac/Linux): https://github.com/nvm-sh/nvm
+NVM for windows: https://github.com/coreybutler/nvm-windows
+Once installed, you can type "nvm" in your CLI to see a red list of commands you can use. Follow instructions on GitHub for proper usage!
+Express
+One of the most common Node.js frameworks is Express. Express is an unopinionated_ (meaning, it doesn't force you to do things any particular way) _framework that excels at allowing you to write APIs. We may include more content on Express here in the future.
+ +TypeScript is a superset of Javascript that introduces new features mostly related to strong typing: this lets you safeguard your variables and functions and helps you catch the most frequent mistakes and bugs from JavaScript code.
+ +TypeScript is contained in .ts files, and using a compiler you can compile it into vanilla JavaScript .js files which run as expected on a computer. If you anticipate doing a lot of work with JavaScript, I highly recommend learning TypeScript - although it isn't necessary for every project, it immensely improves the quality of the coding experience and it can guide you towards mastering tricky concepts from JavaScript like promises and callbacks.
+TypeScript tutorial by NetNinja:
+https://www.youtube.com/playlist?list=PL4cUxeGkcC9gUgr39Q_yD6v-bSyMwKPUI
+TypeScript Basics by JavaBrains: (also includes small project incl. API usage)
+https://www.youtube.com/playlist?list=PLqq-6Pq4lTTanfgsbnFzfWUhhAz3tIezU
+NOTE: here is a more indepth React Guide, the better version!!
+HTML, CSS, and JS are great and all, but what if you want to make a modern, reactive website? Several frontend frameworks exist to empower dynamic, reactive sites, and as of 2021 React is by far the most popular among them. It's a great way to get an introduction into the world of web frameworks and it's a fun tool to use.
+ +Here's a good free overview of the basics of React: https://scrimba.com/learn/learnreact
+Plenty of similar courses are available on YouTube and other course platforms.
+When in doubt, consult the React documentation: https://reactjs.org/docs/
+Note that much of the documentation still uses class-based components, as opposed to function-based components. Nowadays, it is 99% preferable to use function-based components whenever possible. It cuts down on the amount of boilerplate you need to write and enables helpful features from hooks.
+Learn more about React Hooks: https://www.youtube.com/watch?v=TNhaISOUy6Q
+The 2 hooks in particular you should be very familiar with:
+Other hooks that are handy to know about are useRef, useCallback, and useLayoutEffect.
+To learn React, you should know HTML, CSS, and JS before. You can also build React apps with TypeScript instead of JavaScript. https://www.typescriptlang.org/docs/handbook/react.html
+React Context API
+The context API is a tool you can use in React to share state from an upper level component (a provider) to its children. If you have state that needs to be shared across many children, you can use the context API rather than pass everything down manually as props.
+To learn about the context API, I recommend watching this video:
+https://www.youtube.com/watch?v=35lXWvCuM8o
+**React Router **
+If you want to make React websites with multiple pages, you can use React Router. It is a package that enables your app to have multiple routes. This series gives a quick overview of React Router:
+https://www.youtube.com/watch?v=aZGzwEjZrXc&list=PL4cUxeGkcC9gZD-Tvwfod2gaISzfRiP9d&index=21
+React Router is lightweight and best suited for very small projects. If you plan on building a larger website with React, we recommend using Next.js instead - it has a lot more features including pre-rendering pages on the server for SEO optimization. Next.js is also widely used and has industry-level support.
+ +React Redux is a commonly used package for managing global state. It allows you to take care of state in a global store that can be accessed or modified from anywhere in your application.
+https://www.youtube.com/watch?v=CVpUuw9XSjY
+Using React with Typescript
+Here is a great cheatsheet that you should read to get started with using React in combination with Typescript:
+https://github.com/typescript-cheatsheets/react
+That's it! .. for now :)
+Happy hacking!
+ +Hi there! +This website contains tutorials, how-to guides, explanations, +and reference documentation of the things we do at +Tech Start UCalgary.
+If you are looking for our main page, +please visit us at techstartucalgary.com.
+ +