You’d think after all these years I’d have gone and learnt React…
haha. nope. Instead I’ve been learning about smaller frameworks and libraries - like Svelte and Bulma.
But I guess I should stop putting it off and learn it…
Today I’ll be going through developing the tutorial game, as given here.
Introducing React
React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components” - _source: https://reactjs.org/tutorial/tutorial.html_
Comparison: Project Template Size
Just out of interest…
- The Svelte project template is 14 MB in size with packages installed
- The Sapper project template for Svelte is 49 MB in size with packages installed
- The React project template is 204 MB in size with packages installed
Introducing JSX
Javacript XML is an XML-like syntax extension to Javascript that lets us write HTML-like code in our Javascript files.
Of course, as an extension we can’t expect any Javascript engine to understand what’s going on.
React automatically transpiles the code with a tool called Babel
Components
A component is a group of code files that work together to build a single ‘thing’.
In the real world, we could call a written piece of paper a component - it’s made out of wood and ink.
Components can be made up of other components too; for example a book, which is made up of several pieces of paper and a book cover.
In React, components are called ‘component classes’ or ‘component types’, and are the building blocks to modular code - where code can be reused and repurposed!
Function Components and Class Components
The simplest way to create a button component is the below
function createButton(props) {
return <button>{props.text}</button>;
}
Here we have defined a function that returns a JSX element.
We could also have created a class, as shown below
class Button extends React.Component {
render() {
return <button>{this.props.text}</button>;
}
}
According to this website, component classes have an awful lot of cool features, but function components have their benefits
- Functional component are much easier to read and test because they are plain JavaScript functions without state or lifecycle-hooks
- You end up with less code
- They help you to use best practices. It will get easier to separate container and presentational components because you need to think more about your component’s state if you don’t have access to setState() in your component
- The React team mentioned that there may be a performance boost for functional component in future React versions
React.Component subclasses
As seen above, a component class inherits the React.Component
class
When a component (let’s call it Button) is used in a JSX file, its render
method is called.
The render
method in the class returns the visual (JSX / HTML) elements of the component.
Props
Props (short for properties) are values that can supplied to components for them to use.
For example, with either of the above code samples for the Button
component, <Button text=2/>
would render <button>2</button>
.
But we could even pass components as props!
<Button text={<Button text=2/>}/>
would render <button><button>2</button></button>
Slots (Children)
Some inspiration taken from here
With props, we have seen that we can pass data through what looks like JSX attributes (The text
bit of <Button text=.../>
).
But we can also pass data in through a hierarchical structure, like <NewButton>2</NewButton>
.
This is accomplished through the children
property, and can then be accessed during component rendering with [this.]props.children
.
(optional this
, depending if you are declaring a function component or class component)
The below code will make this work
class NewButton extends React.Component {
render() {
return <button>{this.props.children}</button>;
}
}
We could also pass the children as a prop as well - <NewButton children=2/>
is the same as <NewButton>2</NewButton>
; both will render <button>2</button>
.
Named Slots
If you haven’t already realised, with the ability to pass components; or really any form of JSX as a prop - you would be able to create named slots (slots with identifiers)
Scripting
Svelte creates event bind shortcuts: <button click:{clickEvtHandler} />
With React, you gotta do it the old fashion way: <button onClick={clickEvtHandler} />
Though I guess for a component, you could create a click
prop, and pass in a function to that prop
State
Internal properties and values of components are stored in their this.state
attribute.
This attribute is private, and only accessible to the component.
When passed to child components, they will be able to read but not modify state unless explicitly implemented.
Initialising the state of a component is done in the component class' constructor
class Square extends React.Component {
constructor(props) {
super(props);
this.state = {
value: null,
};
}
render() {
return (
<button className="square" onClick={()=>this.setState({value:"X"})}>
{this.state.value}
</button>
);
}
}
To update values in the state, we call the this.setState
method, passing in an object of key-mapped values.
Sharing State
To share state of two components place them in a container, and initialise the state from the container.
Then pass the state as a prop into the children.
Child components can only read values from the state as the state is private.
Only the owner of the state is able to modify its state - luckily we can create a function in the owner component, and pass that function to its children to call.
Purpose for setState - (Im)mutability
When setState
is called, the previous state is saved somewhere; this allows for changes to be observed.
In terms of dynamic components, this has the added benefit of only having to re-render affected parts of components.
setState
is also an asynchronous function - any immediate statement that relies on the successful execution of a setState
call should be passed in through setState
’s callback (second parameter)
Styles (CSS)
Styles are local to the component, and are imported in the component.