ReactPy 0.0.4
React implementation in Python 3, running on the client-side.
Requires Python: >=3.6

# ReactPy

**ReactPy** is a implementation of React in Python using [Brython](https://brython.info/). ReactPy application runs on the client side, which are written in **Python 3**. It's Component based and follows the same virtual DOM and Fiber architecture as ReactJS. ReactPy also supports PYX syntax which is equivalent to JSX in Javascript.

## Getting Started

Creating a ReactPy app is very simple and the process in very much inspired from ReactJS.

<p align="center">
  <img src="https://github.com/RudreshVeerkhare/ReactPy/raw/main/media/ReactPy_init.gif" />
</p>

### Installation

ReactPy has a PyPI package

```
pip install ReactPy
```

### Setting Up

Once ReactPy is installed, then to setup boiler plate -

1. Create an empty folder for your application.
2. Then run the following command to Initialize ReactPy

```sh
python3 -m ReactPy --init
```

### Setup live reload server

ReactPy comes with a simple live reload development server, to use start it -

```sh
python3 -m ReactPy --serve
```

This will start a development server at http://127.0.0.1:5500/

### Create a deployment build

To create a deployment build of your application -

```sh
python3 -m ReactPy --build
```

This will create a `build` directory in project folder. Then this can be very easily deployed to services like [Netlify Drop](https://docs.netlify.com/site-deploys/create-deploys/#drag-and-drop) by uploading `build` folder for deployment.

### Syntax Highlighting

To get syntax highlighting on`.pyx` files in ReactPy applications, install [ReactPy Syntax Highlighter](https://marketplace.visualstudio.com/items?itemName=RudreshVeerkhare.reactpy) in VSCODE from Visual Studio Marketplace.

## Examples

Todo List using ReactPy - [https://react-py-todo.netlify.app/](https://react-py-todo.netlify.app/)

### Passing Props

```python
import ReactPy
from browser import document

def Greetings(props):
    return <h1>Hi, {" " + props["name"]}</h1>

element = <Greetings name="World!"/>
ReactPy.render(element, document.getElementById("root"))
```

### Counter

```python
import ReactPy
from browser import document

def Counter(props):
    count, setCount = ReactPy.useState(0)
    return  <div>
                <h1>Count :{count}</h1>
                <button onClick={lambda e: setCount(count + 1)}>+</button>
                <button onClick={lambda e: setCount(count - 1)}>-</button>
            </div>

element = <Counter/>
ReactPy.render(element, document.getElementById("root"))
```

<p align="center">
  <img src="https://github.com/RudreshVeerkhare/ReactPy/raw/main/media/Counter.gif" />
</p>

### Timer

```python
import ReactPy
from browser import document
from browser.timer import set_interval, clear_interval

def Timer(props):
    seconds, setSeconds = ReactPy.useState(props["timelimit"])
    running, setRunning = ReactPy.useState(False)

    if seconds < 1:
        setRunning(False)

    def _tick():
        setSeconds(lambda s: s - 1)

    def __effect():
        if running:
            print("Set Interval")
            __interval = set_interval(_tick, 1000)
            return lambda: clear_interval(__interval)

    ReactPy.useEffect(__effect, [running])

    color = "red" if not running else "blue"

    return
        <div>
            <div style={{"color": color}}>Seconds : {seconds}</div>
            <button onClick={lambda e: setRunning(lambda r: not r)}>Start / Stop</button>
        </div>

element = <Timer timelimit={5}/>
ReactPy.render(element, document.getElementById("root"))
```

<p align="center">
  <img src="https://github.com/RudreshVeerkhare/ReactPy/raw/main/media/Timer.gif" />
</p>

### Live Input

```python
import ReactPy
from browser import document

def LiveInput(props):
    value, setValue = ReactPy.useState("")

    return
        <div>
            <input value={value + ""} onInput={lambda e: setValue(e.target.value)}/>
            <h1>{value}</h1>
        </div>

element = <LiveInput/>
ReactPy.render(element, document.getElementById("root"))
```

<p align="center">
  <img src="https://github.com/RudreshVeerkhare/ReactPy/raw/main/media/LiveInput.gif" />
</p>

### API Call

```python
import ReactPy
from ReactPy.utils import lmap
from browser import document
from browser.ajax import get

def UserCard(props):
    return <div style={{
            "border": "1px solid black",
            "padding": "5px",
            "margin": "10px",
        }}>
            <h2>{props["name"]}</h2>
            <p>email: {" " + props["email"]}</p>
            <p>website: {" " + props["website"]}</p>
        </div>

def UserList(props):
    users, setUsers = ReactPy.useState([])

    def __effect():
        def _on_complete(res):
            print(res.json)
            setUsers(res.json)

        get("https://jsonplaceholder.typicode.com/users", oncomplete = _on_complete)

    ReactPy.useEffect(__effect, [])

    return  <div>
                {lmap(
                    lambda x: <UserCard name={x["name"]} email={x["email"]} website={x["website"]}/>,
                    users
                ) if len(users) > 0 else <h1>Loading...</h1>}
            </div>

element = <UserList/>
print(element)
ReactPy.render(element, document.getElementById("root"))
```

<p align="center">
  <img src="https://github.com/RudreshVeerkhare/ReactPy/raw/main/media/API%20Call.gif" />
</p>

## Contributions

Check [Contribution.md]() for Detailed Information.

## Note

This project is still in beta, so if you find any bugs please raise an issue.