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”.
Set up a new project⚑
-
Create the project baseline with Create React App. Using this tool avoids:
- Learning and configuring many build tools.
- Optimize your bundles.
- Worry about the incompatibility of versions between the underlying pieces.
So you can focus on the development of your code.
npx create-react-app my-app
-
Delete all files in the
src/
folder of the new project.cd my-app rm src/*
-
Create the basic files
index.css
,index.js
in thesrc
directory. - Run the server:
npm start
.
Start a React + Flask project⚑
- Create the api directory.
mkdir api
- Make the virtualenv.
mkvirtualenv \ --python=python3 \ -a ~/projects/my-app \ my-app
- Install flask.
pip install flask python-dotenv
-
Add a basic file to
api/api.py
.import time from flask import Flask app = Flask(__name__) @app.route('/api/time') def get_current_time(): return {'time': time.time()}
-
Create the
.flaskenv
file.FLASK_APP=api/api.py FLASK_ENV=development
- Make sure everything is alright.
flask run
The basics⚑
Components tell React what to show on the screen. When the data changes, React will efficiently update and re-render the components.
class ShoppingList extends React.Component {
render() {
return (
<div className="shopping-list">
<h1>Shopping List for {this.props.name}</h1>
<ul>
<li>Instagram</li>
<li>WhatsApp</li>
<li>Oculus</li>
</ul>
</div>
);
}
}
// Example usage: <ShoppingList name="Mark" />
ShoppingList
is a React component class, or React component type. A component takes in parameters, called props
(short for “properties”), and returns a hierarchy of views to display via the render
method.
The render
method returns a description of what you want to see on the screen. React takes the description and displays the result. In particular, render returns a React element, which is a lightweight description of what to render.
Most React developers use a special syntax called “JSX” which makes these structures easier to write. The
syntax is transformed at build time to React.createElement('div'). The example above is equivalent to:return React.createElement('div', {className: 'shopping-list'},
React.createElement('h1', /* ... h1 children ... */),
React.createElement('ul', /* ... ul children ... */)
);
The ShoppingList
component above only renders built-in DOM components like <div />
and <li />
. But it can compose and render custom React components too. For example, Use <ShoppingList />
to refer to the whole shopping list. Each React component is encapsulated and can operate independently; this allows the building of complex UIs from simple components.
Pass data between components⚑
Data is passed between components through the props
method.
class Square extends React.Component {
render() {
return (
<button className="square">
{this.props.value}
</button>
);
}
}
class Board extends React.Component {
renderSquare(i) {
return <Square value={i} />;
}
...
}
Use of the state⚑
React components can have state by setting this.state
in their constructors. this.state
should be considered as private to a React component that it’s defined in.
Components need a constructor to initialize the state. In JavaScript classes, it's required to call super when defining the constructor of a subclass. All React component classes that have a constructor should start with a super(props)
call.
class Square extends React.Component {
constructor(props){
super(props);
this.state = {
value: null,
}
}
render() {
...
}
}
Then use the this.setState
method to set the value
...
render() {
return (
<button
className="square"
onClick={() => this.setState({value: 'X'})}
>
{this.state.value}
</button>
);
}
Share the state between parent and children⚑
To collect data from multiple children, or to have two child components communicate with each other, you need to declare the shared state in their parent component instead. The parent component can pass the state back down to the children by using props; this keeps the child components in sync with each other and with the parent component.
First define the parent state
class Square extends React.Component {
render() {
return (
<button
className="square"
onClick={() => this.props.onClick()}
>
{this.props.value}
</button>
);
}
}
class Board extends React.Component {
constructor(props) {
super(props);
this.state = {
squares: Array(9).fill(null),
};
}
handleClick(i) {
const squares = this.state.squares.slice();
squares[i] = 'X';
this.setState({squares: squares});
}
renderSquare(i) {
return <Square
value={this.state.squares[i]}
onClick={() => this.handleClick(i)}
/>;
}
...
}
Since state is considered to be private to a component that defines it, it's not possible to update the parent’s state directly from the children. Instead, A function needs to be passed down from the parent to the children, so the children can call that function when required. For example the onClick={() => this.handleClick(i)}
in the example above.
When a Square
is clicked, the onClick
function provided by the Board
is called. Here’s a review of how this is achieved:
- The
onClick
prop on the built-in DOM<button>
component tells React to set up a click event listener. - When the button is clicked, React will call the
onClick
event handler that is defined inSquare
’srender()
method. - This event handler calls
this.props.onClick()
. TheSquare
’sonClick
prop was specified by theBoard
. - Since the
Board
passedonClick={() => this.handleClick(i)}
toSquare
, theSquare
callsthis.handleClick(i)
when clicked.
So now the state is stored in Board
instead of the individual Square
components. When the Board
’s state changes, the Square
components re-render automatically. In React terms, the Square
components are now controlled components.
Handling data change⚑
There are generally two approaches to changing data. The first one is to mutate the data by directly changing the it’s values. The second is to replace the data with a new copy which has the desired changes.
-
Data Change with Mutation.
var player = {score: 1, name: 'Jeff'}; player.score = 2; // Now player is {score: 2, name: 'Jeff'}
-
Data Change without Mutation.
var player = {score: 1, name: 'Jeff'}; var newPlayer = Object.assign({}, player, {score: 2}); // Now player is unchanged, but newPlayer is {score: 2, name: 'Jeff'} // Or if you are using object spread syntax proposal, you can write: // var newPlayer = {...player, score: 2};
By not mutating directly, several benefits are gained:
- Complex features become simple: Immutability makes complex features much easier to implement.
-
Detecting Changes: Detecting changes in mutable objects is difficult because they are modified directly. This detection requires the mutable object to be compared to previous copies of itself and the entire object tree to be traversed.
Detecting changes in immutable objects is considerably easier. If the immutable object that is being referenced is different than the previous one, then the object has changed.
-
Determining When to Re-Render in React: The main benefit of immutability is that it helps you build pure components in React. Immutable data can easily determine if changes have been made which helps to determine when a component requires re-rendering.
Function components⚑
Function components are a simpler way to write components that only contain a render method and don’t have their own state. Instead of defining a class which extends React.Component
, we can write a function that takes props as input and returns what should be rendered. Function components are less tedious to write than classes, and many components can be expressed this way.
Instead of
class Square extends React.Component {
render() {
return (
<button
className="square"
onClick={() => this.props.onClick()}
>
{this.props.value}
</button>
);
}
}
Use
function Square(props) {
return (
<button ClassName="square" onClick={props.onClick}>
{props.value}
</button>
);
}
Miscellaneous⚑
List rendering⚑
When React renders a list, it stores some information about each rendered list item. Once a list is updated, React needs to determine what has changed. A key property needs to be specified for each list item to differentiate each list item from its siblings. So for:
<li>Ben: 9 tasks left</li>
<li>Claudia: 8 tasks left</li>
<li>Alexa: 5 tasks left</li>
<li key={user.id}>{user.name}: {user.taskCount} tasks left</li>
Could be used. When a list is re-rendered, React takes each list item’s key and searches the previous list’s items for a matching key. If the current list has a key that didn’t exist before, React creates a component. If the current list is missing a key that existed in the previous list, React destroys the previous component. If two keys match, the corresponding component is moved. Keys tell React about the identity of each compone.
Keys tell React about the identity of each component which allows React to maintain state between re-renders. If a component’s key changes, the component will be destroyed and re-created with a new state.
key
is a special and reserved property in React. When an element is created, React extracts the key
property and stores the key
directly on the returned element. Even though key
may look like it belongs in props
, key
cannot be referenced using this.props.key
. React automatically uses key
to decide which components to update. A component cannot inquire about its key
.