reactxpy 1.0.7
Build web apps with React-like syntax in Python
Requires Python: >=3.6

# ReactXPy

**Build web apps with React-like syntax in Python**

ReactXPy is a Python framework that brings React-like syntax and state management (useState) to Flask applications using Alpine.js for client-side reactivity.

## Features

- **React-like Syntax**: Write components using familiar JSX syntax in `.pysx` files
- **`useState` Hook**: Manage state with a familiar getter/setter API
- **Zero Build Step**: Pure Python transpilation on-the-fly  
- **Component Composition**: Build complex UIs by nesting components
- **Dictionary State**: Manage complex data structures like lists of objects
- **List Rendering**: Efficiently render lists using the `<template>` tag and `x-for`
- **Client-Side Reactivity**: Powered by Alpine.js for instant updates

## Installation

```bash
pip install reactxpy
```

## Quick Start

### 1. Create a Simple Counter

Create a file `app.py`:

```python
from reactxpy import use_state, reset_component_state
from flask import Flask

app = Flask(__name__)

def Counter():
    reset_component_state()
    count, set_count = use_state(0)
    
    return f"""
    <div x-data="{{'s1': 0}}">
        <p>Count: <span x-text="s1"></span></p>
        <button @click="{set_count('s1 + 1')}">Increment</button>
        <button @click="{set_count('s1 - 1')}">Decrement</button>
        <button @click="{set_count(0)}">Reset</button>
    </div>
    """

@app.route('/')
def index():
    return f"""
    <!DOCTYPE html>
    <html>
    <head>
        <script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
    </head>
    <body>
        {Counter()}
    </body>
    </html>
    """

if __name__ == '__main__':
    app.run(debug=True)
```

### 2. Using .pysx Files (Recommended)

Create `src/pages/Home.pysx`:

```python
from reactxpy import div, h1, p, button, use_state, reset_component_state

def Home():
    reset_component_state()
    count, set_count = use_state(0)
    
    return <div className="container">
        <h1>Hello, ReactXPy!</h1>
        <p>Count: <span x-text={count.name}></span></p>
        <button @click={set_count(count + 1)}>Increment</button>
        <button @click={set_count(count - 1)}>Decrement</button>
        <button @click={set_count(0)}>Reset</button>
    </div>
```

## useState Hook

The `use_state` hook provides React-like state management:

### Basic Usage

```python
from reactxpy import use_state, reset_component_state

def MyComponent():
    reset_component_state()  # Always call at component start
    count, set_count = use_state(0)
    
    return <div>
        <span x-text={count.name}></span>
        <button @click={set_count(count + 1)}>+</button>
    </div>
```

### Multiple State Variables

```python
def Form():
    reset_component_state()
    name, set_name = use_state("")
    email, set_email = use_state("")
    age, set_age = use_state(0)
    
    return <form>
        <input x-model={name.name} />
        <input x-model={email.name} />
    </form>
```

### Dictionary State (Objects)

You can store complex objects in state:

```python
# Store a list of objects
todos, set_todos = use_state([])

# Add an object to the list
set_todos(todos + [{ "text": "Buy Milk", "id": 1 }])
```

### Lists & Loops

To render lists, use the `template` tag helper with Alpine.js `x-for` directive:

> **⚠️ Important**  
> You must define a `template` helper function in your component file:
> ```python
> from reactxpy.dom import Component
> 
> def template(*args, **kwargs):
>     return Component("template", *args, **kwargs)
> ```

Example:

```python
<ul>
    <template x-for="(item, index) in items" key="item.id">
        <li>
            <span x-text="item.text"></span>
            <button @click="items.splice(index, 1)">Delete</button>
        </li>
    </template>
</ul>
```

## Complete Todo App Example

```python
from reactxpy import use_state, reset_component_state
from reactxpy.dom import Component

def template(*args, **kwargs):
    return Component("template", *args, **kwargs)

def TodoApp():
    reset_component_state()
    new_todo, set_new_todo = use_state("")
    
    # Handler to add object with ID
    add_handler = new_todo.name + " && todos.push({text: " + new_todo.name + ", id: Date.now()}) && (" + new_todo.name + " = '')"

    return <div x-data="{ todos: [] }">
        <h1>My Todos</h1>
        
        <form @submit.prevent={add_handler}>
            <input type="text" x-model={new_todo.name} />
            <button type="submit">Add</button>
        </form>
        
        <ul>
            <template x-for="(todo, index) in todos" key="todo.id">
                <li>
                    <span x-text="todo.text"></span>
                    <button @click="todos.splice(index, 1)">×</button>
                </li>
            </template>
        </ul>
        
        <p>Count: <span x-text="todos.length"></span></p>
    </div>
```

## Component Composition

Create reusable components and pass props:

```python
# components/TodoInput.pysx
def TodoInput(*args, **kwargs):
    props = kwargs.copy()
    if args and isinstance(args[0], dict) and args[0].get("_pysx_props"):
        props.update(args[0])
        
    value = props.get("value")
    placeholder = props.get("placeholder", "")
    
    return <input 
        type="text" 
        placeholder={placeholder} 
        className="todo-input" 
        x-model={value.name} 
    />
```

Use in parent component:

```python
from ..components.TodoInput import TodoInput

def Home():
    reset_component_state()
    new_todo, set_new_todo = use_state("")
    
    return <div>
        <TodoInput value={new_todo} placeholder="What needs to be done?" />
    </div>
```

## Important Notes

> **Note**  
> Use `x-text={state.name}` to display state values instead of f-strings. F-strings convert StateValue to string before component processing.

> **⚠️ Important**  
> Always call `reset_component_state()` at the start of components using `useState` to avoid state leakage between component instances.

## Project Setup

To use ReactXPy in a new Flask project:

1. Install ReactXPy:
   ```bash
   pip install reactxpy
   ```

2. Create your Flask app with Alpine.js:
   ```python
   from flask import Flask
   
   app = Flask(__name__)
   
   @app.route('/')
   def index():
       return '''
       <!DOCTYPE html>
       <html>
       <head>
           <script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
       </head>
       <body>
           <div id="root"></div>
       </body>
       </html>
       '''
   ```

3. Create `.pysx` files for your components

4. Run your app:
   ```bash
   python app.py
   ```

## Documentation

For more detailed documentation, examples, and advanced usage, visit the GitHub repository.

## Roadmap

We're constantly improving ReactXPy! Here's what's coming in future releases:

### v1.1 - Enhanced State Management
- **useEffect Hook**: Side effects and lifecycle management
- **useContext Hook**: Global state management without prop drilling
- **useRef Hook**: DOM references and persistent values
- **Custom Hooks**: Create reusable stateful logic

### v1.2 - Developer Experience
- **Hot Module Replacement**: Instant updates without full page reload
- **DevTools**: Browser extension for debugging components and state
- **Type Hints**: Full TypeScript-style type annotations support
- **Error Boundaries**: Graceful error handling in components

### v1.3 - Performance & SSR
- **Server-Side Rendering**: Pre-render components on the server
- **Hydration**: Seamlessly transition from SSR to client-side
- **Code Splitting**: Load components on demand
- **Memoization**: `useMemo` and `useCallback` hooks

### v1.4 - Advanced Features
- **Suspense**: Handle async data fetching elegantly
- **Portals**: Render components outside the parent hierarchy
- **Fragments**: Group elements without extra DOM nodes
- **Lazy Loading**: Dynamic component imports

### v2.0 - Major Overhaul
- **Virtual DOM**: Optional VDOM for complex apps
- **Native Mobile Support**: Build iOS/Android apps with ReactXPy
- **WebSocket Integration**: Real-time state synchronization
- **Database Integration**: Direct ORM hooks (SQLAlchemy, etc.)

**Want to contribute?** Check out our [GitHub repository](https://github.com/Anishkumar1928/reactxpy) and open an issue or PR!

## License

MIT License

## Links

- **GitHub**: https://github.com/Anishkumar1928/reactxpy
- **PyPI**: https://pypi.org/project/reactxpy/