Svelte - Intro
For people who want to make something appear in a browser, but don’t want to write awful React code.
- Overview
- A Word About HTML & CSS
- Svelte Setup From Scratch
- Selte Setup From Git
- Components
- Props
- State
- Side-Effects
- Fetching Data From Servers and APIs
- Linking From One Screen To Another
- Conclusions
Overview
Concept
Svelte is a tool for auto-generating HTML, CSS, and browser-based Javascript for web app client interfaces.
- Some of the core maintainers of Svelte work for Vercel - a web hosting and “Platform-as-a-Service” (PaaS) company.
- Svelte code files are written in a shorthand mix of HTML, CSS, and Javascript, without many of the complexities of those languages.
- Svelte files are then compiled to regular HTML, CSS, and browser-based Javascript code that can be run in any web browser.
A front-end generator
Svelte programs themselves are not web apps - they comprise neither the front nor the back end.
- Svelte programs are run in order to generate client-side (i.e. front-end) HTML, CSS, and browser-based Javascript code.
- These generated codes together comprise the true front-end of an application.
Components are standardized, reusable, and shareable
The key value proposition of Svelte and other front-end frameworks is that it allows developers to produce standardized reusable code with a minimum of fuss.
- allows developers to write using familiar HTML, CSS, and browser-based Javascript code
- allows for simple creation of reusable custom components
- provides two-way data binding where variable values can be “connected” to visible elements on the screen
- leverages the Node.js Package Manager (NPM) to remove any difficulty from downloading, installing, and configuring additional 3rd-party libraries.
A Word About HTML & CSS
Concept
Any web browser understands the three core front-end web technologies:
- Hypertext Markup Language (HTML) - controls the content present on the web page
- Cascading Style Sheets (CSS) - controls the visual style of the content on the web page
- Javascript (JS) - controls the iteractive behavior of the web page (how does the page change when a user clicks, types, moves them mouse, etc)
Javascript
In addition to controlling the interactive behaviors of web pages running in web browsers, Javascript has found new life in other environments:
- writing Javascript to autogenerate HTML and CSS for the front-end of a web app by using React.js, of course.
- web browser extensions written in Javascript.
- server-side programming with Node.js.
- scripts to automate image editing processes in Adobe Creative Suite.
- interactive music and video composition with Cycling 74’s Max/MSP.
- database queries in MongoDB, Firebase, and others.
- Solidity is designed to be a Javascript-like language that runs on the Ethereum blockchain.
HTML in three slides (slide 1)
For any given web page, HTML code indicates the type of content to show as well as each piece of content’s purpose, or semantic meaning.
- A level 1 heading:
<h1>Puppies For Sale</h1>
- A paragraph:
<p>Buy now while supplies last!</p>
- An image of a lonely puppy:
<img src="images/lonely_puppy.jpg" />
- An article with a level 1 heading, an image of a sad puppy, and a paragraph with a link to another web page:
<article>
<h1>Puppies For Sale</h1>
<img src="images/lonely_puppy.jpg" />
<p>
Buy now while supplies last!
<a href="puppies.html">Learn more</a>
</p>
</article>
HTML in three slides (slide 2)
Many web sites see the same basic content structures repeated across multiple pages, or repeated within a single page. Try it!
<section>
<!-- the first article -->
<article>
<h1>Puppies For Sale</h1>
<img src="images/lonely_puppy.jpg" />
<p>
Buy now while supplies last!
<a href="puppies.html">Learn more</a>
</p>
</article>
<!-- the second article... notice its structural similarity to the first -->
<article>
<h1>Kittens For Sale</h1>
<img src="images/sad_kitten.jpg" />
<p>
Get 'em while they're hot!
<a href="kittens.html">Learn more</a>
</p>
</article>
</section>
HTML in three slides (slide 3)
Actually, we’re more-or-less finished explaining HTML in 2 slides.
What you just learned is how to code for content that will be displayed in the body
of a web page - the part of an HTML document that represents the visible content.
CSS in three slides (slide 1)
For any given web page, CSS code indicates the style to use for the content indicated by the HTML.
- Give all level 2 headings green text:
h2 { color: green; }
- Give all paragraphs a pink background:
p { background-color: pink; }
- Set the dimensions of all images:
img { width: 200px; height: 300px; }
- Give all articles a thick pink dotted border, a bold
serif
font, and lots of space around the contents inside them:
article {
border: 10px dotted pink;
font-family: georgia;
font-weight: bold;
padding: 20px;
}
CSS in three slides (slide 2)
Let’s say you had four paragraphs, and wanted to style only two of them the same. Mark them with a class
attribute in the HTML. If you want to uniquely style only one, mark it with an id
attribute:
<p>Lorem ipsum dolor sit amet.</p>
<p class="my_favorite_paragraphs">Ipsum dolor sit amet lorem.</p>
<p id="a_really_special_paragraph">Dolor sit amet lorem ipsum.</p>
<p class="my_favorite_paragraphs">Ipsum dolor sit amet lorem.</p>
And select only the paragraphs that match these attributes in the CSS:
p.my_favorite_paragraphs {
box-shadow: 5px 5px 10px; /* a drop shadow */
}
p#a_really_special_paragraph {
font-size: 24px; /* relatively big */
}
CSS in three slides (slide 3)
That’s almost it. But there is one very important part of CSS code that we will not address here is how you place elements onto the web page in the location where you want them to go.
There are a variety of ways… the latest greatest is to CSS Flexbox - see a simple example - flexbox is how layouts should be done with React.
- First learn more about basic CSS.
- Then learn more about layouts with CSS flexbox.
Auto-generating HTML & CSS
Now that you have a mastery of HTML & CSS (!), you will use Svelte to autogenerate some of it for you.
- Svelte allows you to easily write reusable bits of HTML, CSS, and browser-based Javascript code called components.
- For example, you can define a template for an
Animal
that contains a heading, photo, and paragraph about a particular animal, and then reuse that template across many pages or in many places within one page.
Svelte Setup From Scratch
Install Node.js
Since React.js is built to run in it, a developer must first install Node.js
- pick the latest stable version for your system
Create project directories
If creating a React app from scratch, first create project directory where everything related to your app - front-end, back-end, and React code - will reside.
mkdir my-app
cd my-app
Since you’ll eventually need it, take the opportunity to make a sub-directory for the back-end code.
mkdir back-end
Create a starter React app
In the project directory, create a React starter project - this will create the basic directory structure, install any necessary dependencies, set up configuration files, and include simple React app starter code that is immediately runnable.
- Call the React app
front-end
, since it will be used to generate the front-end of a web app - this will create afront-end
sub-directory where all React code will live.
npx create-react-app front-end
Remove git
create-react-app
automatically installs git version control tracking into the directory it creates for the React code.
We will want to use git to track our entire project, not just the front-end generator code. So we need to remove git from the front-end
directory.
cd front-end
rm -rf .git # remove the hidden directory where git keeps its files
rm .gitignore # remove the hidden git settings file
Try it out
To preview the app in a non-optimal state, try running it.
Verify that your working directory is front-end
and start up the React preview script.
npm start
This will run the script named start
automatically included in the new app’s configuration file - it launches a preview of the app.
- All Node.js-based applications that use Node’s built-in package manager,
npm
, have a configuration file namedpackage.json
that can include the definition of start scripts like this.
Try generating HTML, CSS, and Javascript files
The previous command previews the app. To generate the proper HTML, CSS, and browser-based Javascript files that will ultimately comprise the app front-end, run the following:
npm run build
This will run the script named build
automatically included in the package.json
configuration file.
- A new sub-directory named
build
will contain the generated files.
Poke around the file system
You should familiarize with the React app files and directories.
build/
- where the generated HTML, CSS, and browser-based Javascript will automatically be placed. Don’t touch this!node_modules/
- where modules that this app depends upon will be automatically installed. Don’t touch this!public/
- contains any static assets that should be copied intobuild/
by the generator, such as favicon images, logo images, etc.src/
- contains the source code files that make up your app… this is where you will work on codesrc/index.js
- code that creates the outline of a basic HTML page and tells React to place the component namedApp
onto the page. Don’t touch this!src/index.css
- CSS code for basic page-wide style settings.src/App.js
- code for theApp
component loaded onto the page.src/App.css
- CSS code for styling the App component.package.json
- the standardnpm
type of configuration file with lots of app settings and a complete list of dependencies
Set up git for the entire project
Navigate to the main project directory where you will initialize git version control tracking.
cd .. # go up a level to the parent directory of both front-end and back-end
git init # install git
Instruct git to ignore files that are not yours
In the main project directory (the parent directory of front-end
and back-end
), create a file named .gitignore
that will inform git of files not to track.
- Copy the contents of this example
.gitignore
into your file. - This
.gitignore
will make sure that the code you write is kept under version control, but not others’ code or auto-generated code.
React Setup From Git
Clone a git repository
If cloning an existing React app, or a fork of an app, stored in a Git remote repository, use git clone
, as with any git repository.
git clone https://github.com/some-username/my-app.git
This will create a new directory named my-app
(or whatever name the repository had) where all the project files are stored.
Navigate into this directory and to any sub-directory where the standard npm
configuration file named package.json
is, and run npm install
in order to install any necessary dependencies for this project.
npm install
Follow along
The React.js code examples in this slide deck are available on GitHub - the code is already set up and ready to run.
-
Fork and clone the companion git repository.
-
Follow the instructions on setting up a project cloned from git.
Components
Concept
A React component is a modular, reusable user interface element.
- Javascript to define components can be written in one of two ways: as a class, or as a function
Component classes
Defining a component with a Javascript class is the most common way, because it was the original way React designed them.
Here is a component class named Hello
that represents a paragraph of text.
class Hello extends Component {
render() {
return <p>Hello world!</p>
}
}
Component functions
Defining a component as a function is now the preferred way and simplifies the code a bit.
function Hello() {
return <p>Hello world!</p>
}
The same function can be written this way, if you remember your Javascript fat arrow syntax:
const Hello = () => <p>Hello world!</p>
JSX
This embedding of HTML-like code into the middle of Javascript code is not ordinary Javacript - it is React’s JSX.
- JSX allows you to write your interface code in an HTML-like way that is familiar to most web and app developers
- React automatically replaces JSX with the equivalent Javascript code to create these interface elements.
const Foo = () => {
return <p>Doesn't this look a lot like HTML code in your Javascript?!</p>
}
Multi-element components
Components can contain multiple user interface elements.
- However, all components must have one ‘root’ element that encompasses all other sub-elements.
- Note the parentheses around the expression that is being returned - this is necessary for multi-element components.
const Hello = () => {
return (
<div>
<h1>React Component</h1>
<p>Hello world!</p>
</div>
)
}
Components are not exactly HTML
While JSX components look almost identical to HTML code, and there is a React component for every HTML element by the same name, they are not HTML and have some slightly different behavior.
For example, to add a class to an HTML element, you use the class
attribute.
<p class="my_favorite_paragraphs">Ipsum dolor sit amet lorem.</p>
To have React render that same HTML, you would have to use the className
attribute in JSX (unlike HTML, all attributes in JSX have lowerCamelCase names):
<p className="my_favorite_paragraphs">Ipsum dolor sit amet lorem.</p>
Supposedly, this is because class
is a reserved word in Javascript, and JSX code is transpiled to Javascript behind-the-scenes. We find that justification lacking.
Components are not exactly HTML (continued)
Attributes in HTML typically have quotes around their values.
<p class="my_favorite_paragraphs">Ipsum dolor sit amet lorem.</p>
If injecting a variable or other expression as the value for an attribute in JSX, you cannot surround the variable in quotes, but it does have to be in curly brackets.
<p className={someVariable}>Ipsum dolor sit amet lorem.</p>
Components are not exactly HTML (continued again)
HTML allows CSS styles to be written inline in an HTML element in a special style
attribute:
<p style="color: blue; background-color: pink;">Ipsum dolor sit amet lorem.</p>
JSX requires a Javascript object to be passed as the style
attribute value.
const pStyle = {
color: 'blue',
backgroundColor: 'pink'; // notice the camelCase style property names - this is Javascript, not CSS!
}
And injected into the JSX without quotes around it.
<p style={pStyle}>Ipsum dolor sit amet lorem.</p>
Components are not exactly HTML (one last time)
Interactive behaviors can be attached to elements in HTML with case-insensitive attributes, such as onclick
, onmouseover
, onmouseout
, and more, and usually including code for a simple function call that is automatically executed when the interactive event occurs.
<p onclick="someFunction()">click me</p>
In React, equivalent behaviors are written with lowerCamelCase attributes and must to refer to a function definition that is automatically called when the interactive event occurs.
<p onClick={someFunction}>click me</p>
Styling components
- React developers are encouraged to use one external CSS file for every one React component file.
- Inline styles, whether in React JSX or in plain HTML, are considered a bad practice - don’t use them!
- For example a component named
Article.js
should have a corresponding CSS file namedArticle.css
- The component file then imports the CSS file using Javascript import syntax.
import "./Article.css"
Styling components (continued)
Given the following JSX:
<article className="intro">
<h1 className="intro-heading">React Component</h1>
<p className="intro-paragraph">Hello world!</p>
</article>
React CSS should select components by their className
attribute, not by the type of HTML element they are rendered as, since this may vary.
.intro {
border: 1px solid red;
}
.intro-heading {
font-family: georgia;
}
/* etc */
Props
Accepting arguments
Props are arguments passed to a component that can influence its content or behavior.
This custom Article
component accepts a props object as its argument and injects some of the values therein into the JSX content:
const Article = props => {
return (
<article>
<h1>{props.heading}</h1>
<p>{props.paragraph}</p>
</article>
)
}
Accepting arguments
Using Javascript’s object destructuring, this function could be rewritten:
const Article = ({ heading, paragraph }) => {
return (
<article>
<h1>{heading}</h1>
<p>{paragraph}</p>
</article>
)
}
Passing props
This custom Section
component includes two Article
components nested within it
- Each
Article
is passed two values to be placed automatically into theprops
parameter object
const Section = () => {
return (
<section>
<article
heading="Puppies for Sale"
paragraph="Get 'em while they last!'"
/>
<article heading="Free Kittens" paragraph="Anytime, anywhere!'" />
</section>
)
}
Functions as arguments
Javascript, of course, has higher-order functions, and can accept function definitions as arguments to a function call.
For example, this component will call any function passed to it as an argument named action
whenever the user clicks the paragraph:
const Card = props => {
return (
<div>
<p onClick={props.action}>Click me!</p>
</div>
)
}
Note the lowerCamelCase spelling of the onClick
attribute, like all JSX attributes.
Functions as arguments (continued)
We could easily pass the definition of the function to run as one of the props
properties in the component that includes the Card
component we defined:
<Card action={ () => { alert("See what I mean? Javascript is fun!") } } />
<Card action={ () => { fetch('https://my.api.mockaroo.com/animals.json?key=d9ddfc40') } } />
Summary
Props are a jargon word for arguments passed to a function that represents a component.
-
when using JSX to include a component, arguments are passed to the component as JSX attributes, e.g.
<Article heading="Free Kittens" />
-
any type of value can be passed as an argument to a component within the props object: a string, number, function definition, object, array, etc.
-
Learn more about components and props
State
Concept
In React, state variables help keep track of the internal state of the component.
- In functional components, state variables must be initialized by calling React’s
useState()
function.
// create a state variable with default value 0
// store a reference to the variable, and a reference to a function that can be called to change its value
const [count, setCount] = useState(0)
This code creates a state variable named count
.
- pass
useState()
an argument with the default value you want the state variable to hold useState()
returns an array with two elements: a reference to that value and the definition of a function you can call to change that value- this returned array is then destructured into two separate variables
Binding
State variables can be injected into any JSX component, just like any other Javascript expression.
<p>You clicked the button {count} times</p>
Binding (continued)
Unlike other expressions, any changes to the value stored in a state variable will be immediately updated in the component.
const MyComponent = () => {
const [count, setCount] = useState(0)
return (
<div>
<p>You clicked the button {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
)
}
Anytime the button is clicked, the state variable is incremented, and the paragraph automatically shows the updated number. Try it
State management
There are a variety of ways to share state between one component and another.
- props drilling - passing state variables from one component as props to a child component - good for simple cases
- context - React’s built-in way to share state among components without passing them as props - recommended for complex cases
- 3rd-party state management “solutions” - Redux, MobX, Apollo, etc. - not recommended
Side-Effects
Concept
Every time React renders a component onto the web page, such as when the page first loads or after a change in state, it is possible to run side-effects.
- The term “side-effect” comes from functional programming.
- In functional programming, the purpose of a function is simply to transform its input into some kind of output, i.e. to take in arguments and return something in response.
- Any other operation unrelated to generating the intended output is a side-effect, not the main purpose of the function.
- Side-effects are considered bad code and are either made impossible or heavily discouraged in functional programming.
- In React, they’re included by design.
The useEffect function
You can define a function within the component that indicates any side-effects you desire, and pass it to React’s useEffect
function.
- React’s code will automatically executed this callback function any time a component is rendered or re-rendered.
- You can define as many separate
useEffect
callbacks as you’d like.
useEffect(() => {
// write whatever code you want run every time the component renders.
console.log("the component has rendered or re-rendered!")
})
Watching for state variable changes
You may not want to run the code within useEffect
’s callback function every time the component renders.
An optional second argument accepts an array. If any variable in the array’s value has changed since last time the component was rendered, the useEffect
callback will be executed.
useEffect(() => {
// write whatever code you want run every time the component renders.
console.log("the component has rendered or re-rendered!")
}, [count])
It is usually the practice to place specific state variables you want to watch into this array.
- Any time those state variables have their values changed, the side-effect code will be run. Try it!
Cleaning up after side-effect code
Some side-effects will need to be undone if a component is removed from the page.
- cleanup functions can be given as the optional return value to any
useEffect
callback.
useEffect(() => {
console.log("the component has rendered or re-rendered!")
return () =>
console.log("the component has been completely removed from the page!")
}, [count])
A practical example
The following useEffect
callback sets up an eventListener - a function to be called automatically whenever the browser window width changes.
- If this component is completely removed from the page, the returned function will be called and it will remove this eventListener.
- This way, any time this component is reloaded into a web page, it can start from scratch without worrying about any previously created eventListeners.
useEffect(() => {
const handleResize = () => setWidth(window.innerWidth)
window.addEventListener("resize", handleResize)
return () => window.removeEventListener("resize", handleResize)
}, [])
Running a side-effect only once
Note the blank array as second argument to useEffect
in the previous example.
- As you know, any changes to values of variables in this array cause the
useEffect
function to run… but this array has no values! - This is the way to make this
useEffect
callback only be executed once when this component is first loaded onto a page. - This side-effect will not be re-called for any re-renders.
Fetching Data From Servers & APIs
Concept
It is often the case that front-end Javascript code fetches data from a back-end web server or API.
- Some or all of that data is often then injected into the visible page
How does front-end code request, receive, and process data from the back-end?
Data structures
Data retrieved from a server can come in any structure. However, it’s not uncommon to receive an array of JSON objects.
;[
{
id: 1,
title: "Mule deer",
country: "Brazil",
price: "$27.77",
description:
"Curabitur in libero ut massa volutpat convallis. Morbi odio odio, elementum eu, interdum eu, tincidunt in, leo. Maecenas pulvinar lobortis est.",
},
{
id: 2,
title: "Monkey, bleeding heart",
country: "Malaysia",
price: "$13.30",
description:
"Integer ac leo. Pellentesque ultrices mattis odio. Donec vitae nisi.",
},
// etc
]
Axios
Axios is a popular 3rd-party module that makes it easy to fetch data from a server.
- The
axios
function makes an asynchronous request to a server - We can wait for that request to resolve and then retrieve the data.
// fetch some mock data about animals for sale
const response = await axios(
"https://my.api.mockaroo.com/animals.json?key=d9ddfc40"
)
// extract the data from the server response
const data = response.data
In the case of React, we can also add that data a state variable we have previously initialized.
setData(response.data)
Iterating through an array of objects
Assuming the variable, data
, contains an array of objects, we can iterate through it the standard way.
data.map(item => (
console.log( item );
))
Outputting JSX from an array
In the case of React, where the data is stored in a state variable, we can place the loop within a JSX component.
<div>
<h1>Animals For Sale</h1>
<section className="animals">
{data.map(item => (
<Animal key={item.id} details={item} />
))}
</section>
</div>
- For every element in the array, an
Animal
component will be rendered. - When rendering multiple instances of the same component, React requires you to pass each a unique identifier named
key
. - Note how we pass the entire object to the component in the
details
props attribute.
Outputting JSX from an array
The Animal
component can now use the object’s information by accessing it in the props
parameter.
const Animal = props => {
return (
<article className="animal">
<h2>{props.details.title}</h2>
<address>{props.details.country}</address>
<strong>{props.details.price}</strong>
<p>{props.details.description}</p>
</article>
)
}
Linking From One Screen To Another
The ‘a’ component
As with its HTML a
element equivalent, the JSX a
component provides the simplest a way to link from one screen to another.
<a href="/puppies/2">Click me!</a>
As with all JSX attributes, Javascript variables or expressions can be injected as the link’s href
attribute value if desired:
<a href={`/puppies/${puppyId}`}>Click me!</a>
Note that while using an a
component to create a link will work, it is not the most efficient way to do so. It will cause the browser to reload an entirely new page, which is not necessary in most cases.
- We will look at using the Link component from the react-router-dom module as a preferable way to create links in a moment
The react-router-dom module
react-router-dom is a 3rd-party module that provides streamlined navigation solutions, including:
- setting up client-side routes - customized URLs in the browser address bar that are mapped to specific components
- setting up a global navigation appears on all screens
- simple linking from one component to another
- and more…
To include it in a project, use npm install
to save it as a dependency in the package.json
configuration file:
npm install --save react-router-dom
Then import into your code:
import { BrowserRouter as Router, Routes, Route } from "react-router-dom" // as n example, we are here importing just those components useful for setting up front-end routes
The react-router-dom module (continued)
For example, the following sets up a few mutually-exclusive front-end routes, indicating the components that should be loaded at each URL.
<Router>
<Header />
<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
<Route path="/animals" element={<AnimalsList />} />
<Route path="/animals/:id" element={<Animal />} />
</Routes>
<Footer />
</Router>
Setting up these route paths is typically done in the top-level component, often called App.js
.
The react-router-dom module (continued again)
The react-router-dom
module also includes a Link
component that can be used to link from one component to another. This is the prefered way to create links from one screen to another when using React.
First, import the Link
component:
import { Link } from "react-router-dom"
Then use it in a JSX component to link to another component:
<Link to="/animals">See all animals</Link>
The react-burger-menu module
react-burger-menu is a 3rd-party module that provides streamlined hamburger menu functionality’:
To include it in a project, use npm install
to save it as a dependency in the package.json
configuration file:
npm install --save react-burger-menu
Then import into your code:
import { slide as Menu } from "react-burger-menu"
Conclusions
Now you have some understanding of using React to generate HTML, CSS, and Javascript for a client-side web pages.
- Now install the React developer tools into your browser.
- A sample full MERN-stack app shows many of the core features of React and
react-router-dom
. - Another React.js-only project with mock login functionality on the front-end but no back-end.
- Thank you. Bye.