Skip to content

Percy Hooks #94

Description

@cryptoquick

Forking from the discussion in #28

Rationale

So, my quick pitch for hooks is, they are a great refinement on the state-management and side-effect management patterns necessary for developing React apps of all sizes and complexities, from small to large apps. They truly offer impressive clarity to React-style virtual DOM apps that I and many others appreciate. It's embraced with a great deal of positivity from the React community, and would be expected by the sort of early-adopters that would be curious enough to think of using Percy in a serious fashion.

I've also found, although Percy components come with a render method, I find myself creating composable stateless functional component analogs in Percy; i.e., functions like this:

fn form_input(store: Rc<RefCell<Store>>, name: Rc<RefCell<String>>) -> VirtualNode {
    let input_store: Rc<RefCell<Store>> = Rc::clone(&store);
    let value_store: Rc<RefCell<Store>> = Rc::clone(&store);
    let input_name: Rc<RefCell<String>> = Rc::clone(&name);
    let value_name: Rc<RefCell<String>> = Rc::clone(&name);

    html! {
        <input
            oninput=move |event: Event| {
                let input_elem = event.target().unwrap();
                let input_elem = input_elem.dyn_into::<HtmlInputElement>().unwrap();
                let value: String = input_elem.value();
                let store: Rc<RefCell<Store>> = Rc::clone(&input_store);
                let name: Rc<RefCell<String>> = Rc::clone(&input_name);
                store.borrow_mut().msg(&Msg::Input(name.borrow().to_string(), value));
            }
            value=get_field(Rc::clone(&value_store), Rc::clone(&value_name))
        />
    }
}

As you can see, this pattern is rather unwieldy, and stores input values in global state, which could be good or bad, but in this case, I'd also need a clear form method to clear the values in this form for a user easily without requiring the user to refresh the page. It'd be best if, in many cases, like UI dropdowns, button states, and form inputs, for example.

The three I find most valuable are:

  1. useState - However, Rust has no means of creating an arbitrary positional destructuring of tuples, (at least, not yet*).
  1. useReducer
  2. useEffect

Examples

Much like React Hooks, I think it'd be good to come up with a similar implementation specific to Percy's virtual DOM implementation.

useState

Local component state management, kept track of in an internal vector indexed by render order.

TODO Add Rust-idiomatic example

useReducer

Used for more global state, which is more persistent throughout the render process. Important to prevent RefCell "prop drilling."

TODO Add Rust-idiomatic example

useEffect

This could be valuable for providing an easy escape hatch into JS functions like fetch and other things used in the wasm-bindgen, web_sys, and js_sys environment. It could provide a signal to the server/SSR to completely ignore code in this closure / macro.

TODO Add Rust-idiomatic example

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions