@ea-lab/reactive-json-docs
Version:
Complete documentation for Reactive-JSON - Components, examples and LLM-parsable guides
301 lines (251 loc) • 10.4 kB
Markdown
# Reactions System
Reactions are a fundamental part of Reactive-JSON's interactivity system. They allow you to respond to user events and perform operations like data updates, network requests, and browser interactions - all through JSON configuration. In the RjBuild, reactions are defined under the `actions` key, just like regular actions, but are distinguished by the presence of the `on` property.
Reactions execute in response to user events (click, change, etc.) to modify application state and trigger behaviors. They differ from [actions](./actions.md), which continuously adapt the UI based on the current data state; reactions are event-driven while actions are state-driven.
## Basic Syntax
Reactions are defined as part of the `actions` array on any element. Each reaction has the following core properties:
- `what`: The name of the reaction to execute.
- `on`: The event that triggers the reaction.
- `when` (optional): Reactions also support optional conditions to control when the reaction should execute. See the [Actions conditional operators documentation](./actions.md#conditional-operators) for detailed information about available condition types.
Beyond these core properties, reactions include reaction-specific properties that vary depending on the reaction type. For example, a `setData` reaction requires `path` and `value` properties, while a `fetchData` reaction needs a `url` property and optional `method` configuration.
```yaml
renderView:
- type: button
content: "Save Text"
actions:
- what: setData # Reaction type
on: click # Triggering event
path: ~.saved_text # Reaction-specific property
value: ~.user_input # Reaction-specific property
when: ~.user_input # Optional condition
isNotEmpty: # Condition value
```
## Basic Reaction Demonstration
This example demonstrates how to set data when a button is clicked.
On the *Save Text* button, we define a `setData` reaction that will set the text field value in the `saved_text` data location when the button is clicked, but only if the text field is not empty.
```yaml
renderView:
- type: TextField
label: "Enter some text:"
dataLocation: ~.user_input
placeholder: "Type something..."
- type: button
content: "Save Text"
actions:
- what: setData # Reaction type
on: click # Triggering event
path: ~.saved_text # Reaction-specific property
value: ~.user_input # Reaction-specific property
when: ~.user_input # Optional condition
isNotEmpty: # Condition value
- type: div
content: ["Saved text: ", ~.saved_text]
actions:
- what: hide # Action (no 'on' property)
when: ~.saved_text # Condition
isEmpty:
data:
user_input: ""
saved_text: ""
```
## Reaction Types
Reactive-JSON provides several built-in reactions:
### Data Management
- **setData**: Sets data at the specified path.
- **addData**: Adds new data to the specified path.
- **removeData**: Removes data from the specified path.
- **moveData**: Moves data from one path to another.
### Network Operations
- **fetchData**: Fetches data from a URL using GET requests.
- **submitData**: Submits data to a server endpoint using POST/PUT/DELETE.
### Browser Operations
- **setClipboardData**: Copies data to the clipboard.
- **redirectNow**: Performs an immediate redirect.
- **triggerEvent**: Triggers a custom event.
- **postMessage**: Sends a message to another window/frame.
For detailed documentation of each reaction, including properties and examples, see their respective documentation pages.
## Event Types
The `on` property accepts standard browser events. These events are the same as those used in standard web development, and their availability depends on the HTML element type. For example, a `change` event will only work on form elements like `input`, `select`, or `textarea`, while a `click` event works on any element.
This example demonstrates the different event types supported by reactions:
```yaml
renderView:
- type: div
content: ["Last event type: ", ~.last_event_type]
attributes:
style:
padding: "10px"
border: "1px solid var(--bs-border-color, #dee2e6)"
borderRadius: "4px"
marginBottom: "10px"
fontWeight: "bold"
- type: TextField
label: "Interactive text field:"
dataLocation: ~.user_input
placeholder: "Click, type, or hover..."
actions:
- what: setData
on: click
path: ~.last_event_type
value: "click"
- what: setData
on: change
path: ~.last_event_type
value: "change"
- what: setData
on: mouseOver
path: ~.last_event_type
value: "mouseOver"
data:
last_event_type: "none"
user_input: ""
```
Common event types:
- `click`: Mouse click (works on any element).
- `change`: Form input change (works on form elements only).
- `mouseOver`: Mouse hover (works on any element).
- `submit`: Form submission (works on form elements only).
- `keyDown`/`keyUp`: Keyboard events (works on focusable elements).
> **Note**: Event names must respect standard React/DOM event naming conventions (camelCase).
## Advanced Features
### Conditional Logic
Reactions support the same conditional operators as actions:
- `when` + `is`/`isNot`: Value equality checks.
- `when` + `isEmpty`: Empty value tests.
- `when` + `contains`/`containsNot`: Content search.
- `when` + `>`, `<`, `>=`, `<=`: Numeric/date comparisons.
- `andConditions`/`orConditions`: Complex condition logic.
### Event Control
Use `stopPropagation: true` to:
1. Prevent event bubbling to parent elements.
2. Stop execution of subsequent actions for the same event.
### Execution Order
- Multiple reactions on the same event execute in the order they are defined.
- Reactions with unmet conditions are skipped.
- Actions (without `on` property) are evaluated separately from reactions.
## Technical Details
- Reactions are triggered by DOM events.
- Multiple reactions can be defined for the same event.
- Reactions are executed in the order they appear in the YAML.
- Reactions can be chained together by modifying data that other reactions depend on.
- Conditional reactions only execute when their conditions evaluate to true.
- The `stopPropagation` property affects both event bubbling and subsequent action execution.
## Limitations
- Event availability depends on the HTML element type (e.g., `change` only works on form elements).
- Network operations require proper CORS configuration.
- Browser operations require appropriate permissions.
- No built-in error handling beyond console logging for network operations.
- Only one network request (fetch/submit) can be active at a time.
- URLs in network operations must be static strings (dynamic URLs not supported).
## Best Practices
1. **Use descriptive conditions**: Make your conditional logic clear and readable.
2. **Handle empty states**: Always consider what happens when data is empty or undefined.
3. **Order matters**: Place more specific conditions before general ones.
4. **Use stopPropagation wisely**: Only use it when you specifically need to prevent event bubbling or stop action execution.
5. **Test network operations**: Ensure your API endpoints return the expected format.
6. **Provide user feedback**: Use visual indicators during loading states.
## Complete Examples
### Data Input and Submission
```yaml
renderView:
- type: TextField
label: "Username"
placeholder: "Enter your username"
dataLocation: ~.form_data.username
- type: TextField
label: "Email"
placeholder: "Enter your email"
inputType: "email"
dataLocation: ~.form_data.email
- type: button
content: Submit
actions:
- what: submitData
on: click
url: "/api/submit"
data:
username: ~.form_data.username
email: ~.form_data.email
when: ~.form_data.username
isNotEmpty:
data:
form_data:
username: ""
email: ""
```
### Conditional Reactions Example
```yaml
renderView:
- type: button
content: "Toggle State"
actions:
- what: setData
on: click
path: ~.button_state
value: "on"
when: ~.button_state
is: "off"
stopPropagation: true
- what: setData
on: click
path: ~.button_state
value: "off"
when: ~.button_state
is: "on"
stopPropagation: true
- type: div
content: ["Button state: ", ~.button_state]
- type: div
content: "Button has been clicked!"
actions:
- what: hide
when: ~.button_state
is: "off"
data:
button_state: "off"
```
### Complex Conditional Logic
```yaml
renderView:
- type: TextField
label: "Enter a number:"
dataLocation: ~.user_input
inputType: "number"
- type: button
content: "Process Number"
actions:
- what: setData
on: click
path: ~.result
value: "Number is valid and positive!"
andConditions:
- when: ~.user_input
isNotEmpty:
- when: ~.user_input
">": 0
- what: setData
on: click
path: ~.result
value: "Number must be positive!"
when: ~.user_input
"<=": 0
- what: setData
on: click
path: ~.result
value: "Please enter a number!"
when: ~.user_input
isEmpty: true
- type: div
content: ["Result: ", ~.result]
actions:
- what: hide
when: ~.result
isEmpty: true
data:
user_input: null
result: null
```
## Next Steps
Congratulations! You've mastered the fundamentals of Reactive-JSON. You now understand how to structure RjBuilds, use templates, and create interactive applications with actions and reactions.
Ready to take your skills further? Explore the **[Advanced Concepts](../advanced-concepts/index.md)** to learn about data mapping, custom plugins, and performance optimization techniques.
## Related Documentation
- **[Actions System](./actions.md)**: Review state-driven UI adaptation.
- **[Template System](./template-contexts-data-binding.md)**: Revisit data binding patterns.