MUNI
inQool as
5. React - basics
What is React? 1
React component tree 2
Function and Class components 2
Props 3
PropsWithChildren 4
Rerendering 5
State 5
State in Class components 5
State in Function component 6
Tic-Tac-Toe in React 7
Grid system 8
Basics 9
Breakpoints 10
Implementation 11
Custom styles in Material UI 12
makeStyles and useStyles 12
Implementation 13
Implementing logic 14
Mouse events 16
Implementation 17
Material Ul icons 19
What is React?
React is a declarative, efficient and flexible JavaScript library for building user interfaces. Components allow you to split the Ul into independent, reusable pieces, and to think about each piece in isolation.
1
MUNI
£9 inQool
React component tree
React components are structured into a hierarchical tree structure. The structure ensures a one-way data flow (via props). The children cannot update the data it receives from its parent. If data needs to be updated, children can receive another prop from the parent, that contains a function to update it. Each component is declaring what will be rendered on the screen based on the props it renders.
Function and Class components
There are two basic ways to define a React component. In the previous lesson it was created by CRA component App. This type of component is called a Function Component.
const App: React.FC =()=>{
return
Hello worlck/div>j
}
You can also write this component via ES6 Class (syntax was mentioned in lesson 2). Class components have a set of methods, each of them evoked in concrete time during the
2
MUNI
£9 inQool
component's life cycle. In the following example, the App component has only a single lifecycle method render which serves the same purpose as the return value of a function component. In other words, it renders JSX on the screen.
class App extends React.Component { render() {
return ;
}
}
Since we will be using the newer function components and hooks we won't go deep into the class component's lifecycle and other related topics. While React developers said that there are no plans of deprecating class components, we can safely assume that they won't be receiving any new features.
Props
React components accept arbitrary values (called "props" which is short for properties) and return React elements describing what should appear on the screen. We can expand the example of the function component above with props like this.
type Props = { name: string }j
const App: React.FC = props => { return
Hello {props.name}
j
For example Typography component from MaterialUI in the following snippet uses a variant prop.
•typography variant="h5">Sign in
It's common to use destructuring on props, so many examples you come across will look like this.
3
MUNI
£9 inQool as
const App: React.FC = ({ name }) => { return
Hello {name}
j
PropsWithChildren
When you inspect the type of props you get when using TypeScript, you can see that your Props type is wrapped in a PropsWithChildren helper which adds the children: React. ReactNode to your props. The children prop is a special prop that each component has and it's value is equal to what you pass to it between it's opening and closing tags.
type Props = { title: string }j
const Button: React.FC = ({ title, children }) => { return j
}J
// Usage
Here you can see one simple example where a button component simply passes the children prop to the DOM element it renders.
You can also change the type of children prop (which TypeScript will also remind you of) to anything else. Most commonly it's used to expect an array of components or in a pattern called Render props. You can find this pattern used in various component libraries and it may look something like this.
// Type of children is (close: () => void) => ReactNode instead of ReactNode
Rerendering
Important note about props is that the component is rerendered each time the props change. In class components, you could use multiple methods to change this behaviour, but in function components there was no such a thing until Hooks came along. Hooks are what allows functional components with linear code execution to have things like persistent state and other features, but more on Hooks later.
State
Each component (class or function) is able to store local state. Below we will go over differences in these two approaches.
State in Class components
type Props = {};
type State = { foo: string }j
class App extends React.Component { constructor(props: Props) { super(props)j this.state = { foo: 'bar'j
}
renderQ {
return
{this.state.foo}
j
}
}
State and props are key mechanisms in React and both invoke rerendering the component after the change of it's values. It means that if we have a button element calling setstate method (reserved method in Class component, which sets values into state) we can change the value of
5
MUNI
£9 inQool
this . state . f 00 like this...
... and then the state will contain the value of "baz" under the foo key and the component will also be rerendered.
State in Function component
import Reactj { FCj useState } from 'react'j
const App: FC = () => {
const [foOj setFoo] = useState('bar')j return
{foo}
j
In function components there is no constructor nor reserved setState method. We need to use the already mentioned Hooks, specifically useState hook.
This hook returns a tuple consisting of current value (foo) and setter (setFoo) and takes an optional value which if provided will be the initial value of this state.
Note:
Array destructuring is used to extract the value and setter from the returned value, therefore you can choose any names for these two variables. You should still follow the convention [x, setx] whenever possible though.
Note:
If an initial value is provided, the type of the return value is inferred from it. However if there is no initial value you should explicitly provide the type. Also in this case the type will automatically be expanded with undefined.
const [foOj setFoo] = useState(); // Type of foo is string | undefined
There may be cases (we will even come across one in this week's task) where you want to change state based on its current value. Most commonly this is used for boolean state which you simply want to toggle between true and false. For this use case, the set function instead of value can accept a function that provides you with the real and up to date value of its state (this is usually most important when using state setter in asynchronous code).
6
MUNI
£9 inQool as
const [flag., setFlag] = useState(false);
const toggleFlag = () => setFlag(prev => Iprev);
Tic-Tac-Toe in React
Now let's demonstrate all the basics on a Tic-Tac-Toe game example. Our starting point will be a clean Create React App project.
yarn create react-app tic-tac-toe --template typescript
First create a new components folder and do some minor cleanup of CRA template. This project will contain multiple components declared in multiple files so it's useful to organise your files a bit. We can now prepare basic components of the game. Create two new files, Square . tsx and Board. tsx in the components folder.
Square component will represent one field in the tic tac toe board.
import Reactj { FC } from "react";
const Square: FC = ({ children }) => (