====== React Py ======
{{ ::reactpy-logo-landscape.svg |50px}}
React Py és una llibreria que ens permet crear interfaces amb python sense emprar javascript.
Es basa, com fa ReactJS, en components per a construir la interfícies de l'aplicació client. Té l'avantatge d'utilitzar el llenguatge Python. Per a desenvolupadors habituats a treballar amb Django o Flask els hi resultarà molt més còmode que utilitzar Javascript.
Tot i així, els navegadors no són capaços d'executar codi en Python, i per tant, per a producció o per a proves en un navegador, l'entorn de desenvolupament compila el codi python a javascript
Trobaràs la seva documentació a [[https://reactpy.dev/docs/index.html|https://reactpy.dev/docs/index.html]].
Tot i estar força incomplerta podem veure com es codifiquen molts dels elements típics de ReactJS en ReactPy. Des d'esdeveniments al més pur estil de javascript, fins a Hooks com [[https://reactpy.dev/docs/reference/hooks-api.html#use-state|useState]], [[https://reactpy.dev/docs/reference/hooks-api.html#use-effect|useEffect]], [[https://reactpy.dev/docs/reference/hooks-api.html#use-context|useContext]], [[https://reactpy.dev/docs/reference/hooks-api.html#use-reducer|useReducer]], [[https://reactpy.dev/docs/reference/hooks-api.html#use-callback|useCallBack]], [[https://reactpy.dev/docs/reference/hooks-api.html#use-memo|useMemo]] i [[https://reactpy.dev/docs/reference/hooks-api.html#use-ref|useRef]]
===== Un primer exemple =====
La millor forma d'entendre com funciona és creant un petit projecte.
==== Instal·lació de dependències ====
Primer començarem instal·lant les dependències
''pip3 install 'reactpy[fastapi]'''
fastapi només és necessari per a aixecar el projecte
Encabat instal·lem uvicorn, que ens permetrà aixecar l'entorn de desenvolupament. Seria l'equivalen al node que emprem amb ReactJS
''pip3 install 'uvicorn[standard]'''
==== Creació del primer component ====
Després d'això creem un fitxer main.py, on importarem les llibreries
from reactpy import component,html,hooks
from reactpy.backend.fastapi import configure
from fastapi import FastAPI
#....
#Al final del codi
app = FastAPI()
configure (app, HelloWorld )
I creem el primer component
@component
def HelloWorld():
return html.div("Hello World")
Observa com el retorn es fa emprant l'objecte html, i els elements que hi vulguem visualitzar.
Pots obtenir més informació a
[[https://reactpy.dev/docs/guides/creating-interfaces/html-with-reactpy/index.html|HTML With ReactPy]]
Un altre exemple d'elements renderitzats per html. Observa com creem una estructura d'elements amb més elements i elements fills:
html.div(
html.h1("My Todo List"),
html.ul(
html.li("Build a cool new app"),
html.li("Share it with the world!"),
),
)
==== Esdeveniments ====
Els elements html també poden rebre esdeveniments, i això ho podem expressar com segueix:
return html.button({"on_click": handle_event}, display_text)
Tens més exemples a [[https://reactpy.dev/docs/guides/adding-interactivity/index.html#section-1-responding-to-events|Responding to Events]]
==== Components amb estat ====
Com a ReactJS, un dels elements més potents que tenen aquests frameworks són els estats. A ReactPy també tenim aquesta opció, com esmentavem abans, i ens permet renderitzar el nostre SPA a canvis de qualsevol valor. A [[https://reactpy.dev/docs/guides/adding-interactivity/index.html#section-2-components-with-state|Components with state]] tens més exemples.
Un exemple senzill:
choices, set_choices = hooks.use_state([])
resposta, set_resposta = hooks.use_state("")
Aquí creem dues variable d'estat, la primera inicialitzada amb un array, i la segona amb una cadena de text
En un mètode que gestioni un esdeveniment podem, per exemple, canviar el seu valor:
def handle_choices(event):
set_resposta("Gràcies per la teva resposta")
I aquesta variable d'estat renderitzar-se amb el component
return html.div(resposta)
Cal recordar, que a l'igual que amb ReactJS, un canvi de valor d'una variable d'estat que es rendertiza en l'html, obliga re-rendertizar l'html, sempre sense recàrrega de l'html, ja que és un spa.
Finalment indicar que tenim altres hooks, propis de React, com ja he esmentat a l'inici de l'article, però que aquí no detallarem
Teniu un [[https://github.com/armandmt/reactpy|repositori de github]] on podeu veure un projecte sencer. En ell es consulta dues API's per oblir dos select
A cotinuació es mostra un fragment del codi
from reactpy import component,html,hooks
from reactpy.backend.fastapi import configure
from fastapi import FastAPI
import requests
@component
def Item(text, initial_done=False):
done, set_done = hooks.use_state(initial_done)
def handle_click(event):
set_done(not done)
attr= {"style": {"color": "green"}} if done else {"style": {"color": "red"}}
if done:
return html.li(attr, text)
else:
return html.li(
html.span(attr, text),
html.button({ "on_click": handle_click }," Fet!")
)
@component
def Todos(items):
choices, set_choices = hooks.use_state([])
resposta, set_resposta = hooks.use_state("")
def handle_choices(event):
set_resposta("Gràcies per la teva resposta")
def handle_click(event):
id = event['target']['value']
# obtenim llista de choices
choices_API = requests.get('http://localhost:8002/api/get_choices/'+id)
resultat = choices_API.json()
items_choices= resultat['choices']
set_choices( [
html.option( { "value":i['id']},i['choice_text'])
for i in items_choices
])
list_item_elements = [
html.option( { "value":i['id']},i['question_text'])
for i in items
]
return html.div (
html.select({"on_change": handle_click },list_item_elements),
html.select({"on_change": handle_choices },choices),
html.div(resposta)
)
@component
def HelloWorld():
response_API = requests.get('http://localhost:8002/api/get_questions')
resultat = response_API.json()
questions = resultat['questions']
# for parcial in resultat:
# print(parcial['question_text'])
for parcial in questions:
print(parcial['question_text'])
return html._(
html.h1("Llista de tasques ! "),
html.div(Todos(questions)),
html.ul(
Item("Aprendre React amb Python", True),
Item("Dominar Django com un pro"),
Item("Sobreviure a un projecte amb Laravel")
)
)
app = FastAPI()
configure (app, HelloWorld )