Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reacting to Input with State docs #1099

Draft
wants to merge 7 commits into
base: new-docs
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/examples/managing_state/all_possible_states.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from reactpy import hooks

# start
is_empty, set_is_empty = hooks.use_state(True)
is_typing, set_is_typing = hooks.use_state(False)
is_submitting, set_is_submitting = hooks.use_state(False)
is_success, set_is_success = hooks.use_state(False)
is_error, set_is_error = hooks.use_state(False)
37 changes: 37 additions & 0 deletions docs/examples/managing_state/alt_stateful_picture_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from reactpy import component, event, hooks, html


# start
@component
def picture():
is_active, set_is_active = hooks.use_state(False)

if is_active:
return html.div(
{
"className": "background",
"onClick": lambda event: set_is_active(False),
},
html.img(
{
"onClick": event(stop_propagation=True),
"className": "picture picture--active",
"alt": "Rainbow houses in Kampung Pelangi, Indonesia",
"src": "https://i.imgur.com/5qwVYb1.jpeg",
}
),
)
else:
return html.div(
{"className": "background background--active"},
html.img(
{
"onClick": event(
lambda event: set_is_active(True), stop_propagation=True
),
"className": "picture",
"alt": "Rainbow houses in Kampung Pelangi, Indonesia",
"src": "https://i.imgur.com/5qwVYb1.jpeg",
}
),
)
16 changes: 16 additions & 0 deletions docs/examples/managing_state/basic_form_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from reactpy import component, html


# start
@component
def form(status="empty"):
if status == "success":
return html.h1("That's right!")

return html.fragment(
html.h2("City quiz"),
html.p(
"In which city is there a billboard that turns air into drinkable water?"
),
html.form(html.textarea(), html.br(), html.button("Submit")),
)
3 changes: 3 additions & 0 deletions docs/examples/managing_state/conditional_form_component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
.Error {
color: red;
}
35 changes: 35 additions & 0 deletions docs/examples/managing_state/conditional_form_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from reactpy import component, html


# start
@component
def error(status):
if status == "error":
return html.p(
{"className": "error"}, "Good guess but a wrong answer. Try again!"
)

return ""


@component
def form(status="empty"):
# Try "submitting", "error", "success":
if status == "success":
return html.h1("That's right!")

return html.fragment(
html.h2("City quiz"),
html.p(
"In which city is there a billboard that turns air into drinkable water?"
),
html.form(
html.textarea({"disabled": "True" if status == "submitting" else "False"}),
html.br(),
html.button(
{"disabled": (True if status in ["empty", "submitting"] else "False")},
"Submit",
),
error(status),
),
)
13 changes: 13 additions & 0 deletions docs/examples/managing_state/multiple_form_components.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
section {
border-bottom: 1px solid #aaa;
padding: 20px;
}
h4 {
color: #222;
}
body {
margin: 0;
}
.Error {
color: red;
}
15 changes: 15 additions & 0 deletions docs/examples/managing_state/multiple_form_components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# start
from conditional_form_component import form

from reactpy import component, html


@component
def item(status):
return html.section(html.h4("Form", status, ":"), form(status))


@component
def app():
statuses = ["empty", "typing", "submitting", "success", "error"]
return html.fragment([item(status) for status in statuses])
5 changes: 5 additions & 0 deletions docs/examples/managing_state/necessary_states.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from reactpy import hooks

# start
answer, set_answer = hooks.use_state("")
error, set_error = hooks.use_state(None)
28 changes: 28 additions & 0 deletions docs/examples/managing_state/picture_component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
body {
margin: 0;
padding: 0;
height: 250px;
}

.background {
width: 100vw;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
background: #eee;
}

.background--active {
background: #a6b5ff;
}

.picture {
width: 200px;
height: 200px;
border-radius: 10px;
}

.picture--active {
border: 5px solid #a6b5ff;
}
16 changes: 16 additions & 0 deletions docs/examples/managing_state/picture_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from reactpy import component, html


# start
@component
def picture():
return html.div(
{"className": "background background--active"},
html.img(
{
"className": "picture",
"alt": "Rainbow houses in Kampung Pelangi, Indonesia",
"src": "https://i.imgur.com/5qwVYb1.jpeg",
}
),
)
6 changes: 6 additions & 0 deletions docs/examples/managing_state/refactored_states.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from reactpy import hooks

# start
answer, set_answer = hooks.use_state("")
error, set_error = hooks.use_state(None)
status, set_status = hooks.use_state("typing") # 'typing', 'submitting', or 'success'
69 changes: 69 additions & 0 deletions docs/examples/managing_state/stateful_form_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import asyncio

from reactpy import component, event, hooks, html


async def submit_form(*args):
await asyncio.wait(5)


# start
@component
def error_msg(error):
if error:
return html.p(
{"className": "error"}, "Good guess but a wrong answer. Try again!"
)
else:
return ""


@component
def form(status="empty"):
answer, set_answer = hooks.use_state("")
error, set_error = hooks.use_state(None)
status, set_status = hooks.use_state("typing")

@event(prevent_default=True)
async def handle_submit(event):
set_status("submitting")
try:
await submit_form(answer)
set_status("success")
except Exception:
set_status("typing")
set_error(Exception)

@event()
def handle_textarea_change(event):
set_answer(event["target"]["value"])

if status == "success":
return html.h1("That's right!")
else:
return html.fragment(
html.h2("City quiz"),
html.p(
"In which city is there a billboard that turns air into drinkable water?"
),
html.form(
{"onSubmit": handle_submit},
html.textarea(
{
"value": answer,
"onChange": handle_textarea_change,
"disabled": (True if status == "submitting" else "False"),
}
),
html.br(),
html.button(
{
"disabled": (
True if status in ["empty", "submitting"] else "False"
)
},
"Submit",
),
error_msg(error),
),
)
30 changes: 30 additions & 0 deletions docs/examples/managing_state/stateful_picture_component.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from reactpy import component, event, hooks, html


# start
@component
def picture():
is_active, set_is_active = hooks.use_state(False)
background_className = "background"
picture_className = "picture"

if is_active:
picture_className += " picture--active"
else:
background_className += " background--active"

@event(stop_propagation=True)
def handle_click(event):
set_is_active(True)

return html.div(
{"className": background_className, "onClick": set_is_active(False)},
html.img(
{
"onClick": handle_click,
"className": picture_className,
"alt": "Rainbow houses in Kampung Pelangi, Indonesia",
"src": "https://i.imgur.com/5qwVYb1.jpeg",
}
),
)
2 changes: 1 addition & 1 deletion docs/examples/tutorial_tic_tac_toe/tic_tac_toe.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def inner(event):
f"Winner: {winner}" if winner else "Next player: " + ("X" if x_is_next else "O")
)

return html._(
return html.fragment(
html.div({"className": "status"}, status),
html.div(
{"className": "board-row"},
Expand Down
9 changes: 4 additions & 5 deletions docs/mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,7 @@ nav:
- Add React to an Existing Project: learn/add-react-to-an-existing-project.md
- Setup:
- Editor Setup: learn/editor-setup.md
# - ReactPy Developer Tools 🚫: learn/react-developer-tools.md
- Tools, Modules, and Packages 🚧: learn/extra-tools-and-packages.md
- Tools, Libraries, and Packages: learn/tools-and-packages.md
# - More Tutorials:
# - "Tutorial: React Bootstrap 🚫": learn/tutorial-react-bootstrap.md
# - "Tutorial: Material UI 🚫": learn/tutorial-material-ui.md
Expand All @@ -35,7 +34,7 @@ nav:
- Updating Objects in State 🚧: learn/updating-objects-in-state.md
- Updating Arrays in State 🚧: learn/updating-arrays-in-state.md
- Managing State:
- Reacting to Input with State 🚧: learn/reacting-to-input-with-state.md
- Reacting to Input with State: learn/reacting-to-input-with-state.md
- Choosing the State Structure 🚧: learn/choosing-the-state-structure.md
- Sharing State Between Components 🚧: learn/sharing-state-between-components.md
- Preserving and Resetting State 🚧: learn/preserving-and-resetting-state.md
Expand Down Expand Up @@ -85,8 +84,8 @@ nav:
- Components and Hooks must be pure 🚧: reference/components-and-hooks-must-be-pure.md
- React calls Components and Hooks 🚧: reference/react-calls-components-and-hooks.md
- Rules of Hooks 🚧: reference/rules-of-hooks.md
# - Template Tags:
# - Jinja 🚧: reference/jinja.md
- Template Tags:
- Jinja 🚧: reference/jinja.md
- Protocol Structure 🚧: reference/protocol-structure.md
- Client API 🚧: reference/client-api.md
- About:
Expand Down
2 changes: 1 addition & 1 deletion docs/overrides/home.html
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ <h1>Add interactivity wherever you need it</h1>
<h1>Go full-stack with a framework</h1>
<p>
ReactPy is a library. It lets you put components together, but it doesn't prescribe how to do routing and
data fetching. To build an entire app with ReactPy, we recommend a backend framework like
data fetching. To build an entire app with ReactPy, you can leverage a backend framework like
<a href="https://www.djangoproject.com/">Django</a> or <a href="https://www.starlette.io/">Starlette</a>.
</p>
<a href="{{ page.next_page.url | url }}" class="md-button md-button--primary">
Expand Down
2 changes: 1 addition & 1 deletion docs/overrides/homepage_examples/add_interactivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def searchable_video_list(videos):
search_text, set_search_text = use_state("")
found_videos = filter_videos(videos, search_text)

return html._(
return html.fragment(
search_input(
{"onChange": lambda event: set_search_text(event["target"]["value"])},
value=search_text,
Expand Down
Loading