Quick start
OverviewΒΆ
Welcome to the ReactPy documentation! This page will give you an introduction to the 80% of React concepts that you will use on a daily basis.
You will learn
- How to create and nest components
- How to add markup and styles
- How to display data
- How to render conditions and lists
- How to respond to events and update the screen
- How to share data between components
Creating and nesting componentsΒΆ
React apps are made out of components. A component is a piece of the UI (user interface) that has its own logic and appearance. A component can be as small as a button, or as large as an entire page.
React components are Python functions that return markup:
@component
def my_button():
return html.button("I'm a button!")
Now that you've declared my_button
, you can nest it into another component:
@component
def my_app():
return html.div(
html.h1("Welcome to my app"),
my_button(),
)
Have a look at the result:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
1 |
|
Adding stylesΒΆ
In React, you specify a CSS class with className
. It works the same way as the HTML class
attribute:
html.img({"className": "avatar"})
Then you write the CSS rules for it in a separate CSS file:
/* In your CSS */
.avatar {
border-radius: 50%;
}
React does not prescribe how you add CSS files. In the simplest case, you'll add a <link>
tag to your HTML. If you use a build tool or web framework, consult its documentation to learn how to add a CSS file to your project.
Displaying dataΒΆ
You can fetch data from a variety of sources and directly embed it into your components. You can also use the style
attribute when your styles depend on JavaScript variables.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
1 2 3 4 5 6 7 |
|
1 |
|
Conditional renderingΒΆ
In React, there is no special syntax for writing conditions. Instead, you'll use the same techniques as you use when writing regular Python code. For example, you can use an if
statement to conditionally include components:
@component
def my_component():
if is_logged_in:
content = admin_panel()
else:
content = login_form()
return html.div(content)
If you prefer more compact code, you can use the ternary operator.:
@component
def my_component():
return html.div(admin_panel() if is_logged_in else login_form())
When you don't need the else
branch, you can also use a shorter logical and
syntax:
@component
def my_component():
return html.div(is_logged_in and admin_panel())
All of these approaches also work for conditionally specifying attributes. If you're unfamiliar with some of this Python syntax, you can start by always using if...else
.
Rendering listsΒΆ
You will rely on Python features like for
loop and list comprehension to render lists of components.
For example, let's say you have an array of products:
products = [
{"title": "Cabbage", "id": 1},
{"title": "Garlic", "id": 2},
{"title": "Apple", "id": 3},
]
Inside your component, use list comprehension to transform an array of products into an array of <li>
items:
list_items = [html.li({"key": product["id"]}, product["title"]) for product in products]
Notice how <li>
has a key
attribute. For each item in a list, you should pass a string or a number that uniquely identifies that item among its siblings. Usually, a key should be coming from your data, such as a database ID. React uses your keys to know what happened if you later insert, delete, or reorder the items.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
1 |
|
Responding to eventsΒΆ
You can respond to events by declaring event handler functions inside your components:
@component
def my_button():
def handle_click(event):
print("You clicked me!")
return html.button(
{"onClick": handle_click},
"Click me",
)
Notice how "onClick": handle_click
has no parentheses at the end! Do not call the event handler function: you only need to pass it down. React will call your event handler when the user clicks the button.
Updating the screenΒΆ
Often, you'll want your component to "remember" some information and display it. For example, maybe you want to count the number of times a button is clicked. To do this, add state to your component.
First, import use_state
from React:
from reactpy import use_state
Now you can declare a state variable inside your component:
@component
def my_button():
count, set_count = use_state(0)
# ...
Youβll get two things from use_state
: the current state (count
), and the function that lets you update it (set_count
). You can give them any names, but the convention is to write something, set_something = ...
.
The first time the button is displayed, count
will be 0
because you passed 0
to use_state()
. When you want to change state, call set_count()
and pass the new value to it. Clicking this button will increment the counter:
@component
def my_button():
count, set_count = use_state(0)
def handle_click(event):
set_count(count + 1)
return html.button({"onClick": handle_click}, f"Clicked {count} times")
React will call your component function again. This time, count
will be 1
. Then it will be 2
. And so on.
If you render the same component multiple times, each will get its own state. Click each button separately:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 2 3 4 |
|
1 |
|
Notice how each button "remembers" its own count
state and doesn't affect other buttons.
Using HooksΒΆ
Functions starting with use
are called Hooks. use_state
is a built-in Hook provided by React. You can find other built-in Hooks in the API reference. You can also write your own Hooks by combining the existing ones.
Hooks are more restrictive than other functions. You can only call Hooks at the top of your components (or other Hooks). If you want to use use_state
in a condition or a loop, extract a new component and put it there.
Sharing data between componentsΒΆ
In the previous example, each my_button
had its own independent count
, and when each button was clicked, only the count
for the button clicked changed:
However, often you'll need components to share data and always update together.
To make both my_button
components display the same count
and update together, you need to move the state from the individual buttons "upwards" to the closest component containing all of them.
In this example, it is my_app
.
Now when you click either button, the count
in my_app
will change, which will change both of the counts in my_button
. Here's how you can express this in code.
First, move the state up from my_button
into my_app
:
@component
def my_app():
count, set_count = use_state(0)
def handle_click(event):
set_count(count + 1)
return html.div(
html.h1("Counters that update separately"),
my_button(),
my_button(),
)
@component
def my_button():
# ... we're moving code from here ...
Then, pass the state down from my_app
to each my_button
, together with the shared click handler. You can pass information to my_button
using props:
@component
def my_app():
count, set_count = use_state(0)
def handle_click(event):
set_count(count + 1)
return html.div(
html.h1("Counters that update together"),
my_button(count, handle_click),
my_button(count, handle_click),
)
The information you pass down like this is called props. Now the my_app
component contains the count
state and the handle_click
event handler, and passes both of them down as props to each of the buttons.
Finally, change my_button
to read the props you have passed from its parent component:
@component
def my_button(count, on_click):
return html.button({"onClick": on_click}, f"Clicked {count} times")
When you click the button, the on_click
handler fires. Each button's on_click
prop was set to the handle_click
function inside my_app
, so the code inside of it runs. That code calls set_count(count + 1)
, incrementing the count
state variable. The new count
value is passed as a prop to each button, so they all show the new value. This is called "lifting state up". By moving state up, you've shared it between components.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
|
1 2 3 4 |
|
1 |
|
Next StepsΒΆ
By now, you know the basics of how to write React code!
Check out the Tutorial to put them into practice and build your first mini-app with React.