RisingStack / react-easy-state

Simple React state management. Made with ❤️ and ES6 Proxies.
MIT License
2.56k stars 104 forks source link

[Idea] ES6 classes + pure React functions #173

Open brillout opened 4 years ago

brillout commented 4 years ago
import React from 'react';
import ReactDOM from 'react-dom';
import { reactiveView } from '@risingstack/react-easy-state';

@reactiveView
class MyForm {
  inputText = 'change me';
  view() {
    // This view is reactive: when the user changes
    // the `<input>` value, this view is re-rendered.
    return <>
      <div>I'm automatically refreshed: {this.inputText}</div>
      <input
        type='text'
        defaultValue={this.inputText}
        onChange={ev => {
          this.inputText = ev.target.value;
        }}
      />
    </>;
  }
}

const my_form = new MyForm();
render(<my_form.view/>);

Why not using ES6 classes for state management while using a view property to define how instances are rendered. The view property is a pure and stateless React function which is made reactive by @reactiveView.

EDIT: This is not about using React class components, it's about using ES6 classes to do state management together with pure/stateless React functions.

Thoughts? :-)

cc @lostpebble (I actually wanted to use PullState but for my use case I don't need anything sophisticated and something à la MobX should suffice.)

solkimicreb commented 4 years ago

This could be doable with the current API, the only missing feature is the ability to pass classes to store. People request that feature from time to time and we always ditched it so far, I guess it's time to revisit it with the team 🙂

If we add this feature you can do what you described with a slightly different syntax:

@store
@view
class Todo extends Component {
  // your logic here ...

  // 'render' instead of 'view'
  render () {}
}

In the meantime I think you can do a userland implementation with a bit of work:

function reactiveView (Comp) {
  return view(new Proxy(Comp, {
    construct (target, args, ctx) {
      return Reflect.construct(target, args, store(ctx))
    }
  }))
}

I didn't test it, but I think it should work.

brillout commented 4 years ago

I don't want to use React class components. I want to use ES6 classes for state management and use pure and stateless React functions to define how instances should be rendered.

In the meantime I think you can do a userland implementation with a bit of work:

That's lovely, I'm currently using my own hacked-together thing but I'll try this.

People request that feature from time to time

Yes I've seen that, such as https://github.com/RisingStack/react-easy-state/issues/89. But what they propose is using React class components. What I propose is using ES6 classes to do state management.

Thanks for having built React Easy State btw., I like its simplicity.

brillout commented 4 years ago

I got a prototype working:

I'm excited :-) I'm going to try this in production on the web app I'm currently working on.

solkimicreb commented 4 years ago

@brillout any news on this? How do you manage component lifecycle? Do you use hooks inside the view method?

brillout commented 4 years ago

Hi @solkimicreb !

No news in particular; the prototype I've been working on works so far.

It's not polished (yet) but I'll get back to you if/once I've polished all rough edges.

So far I'm happy to be able to use plain simple ES6 classes to do state management.

brillout commented 4 years ago

As for your questions; the current implementation I'm using is here and it's used like this:

As you can see the view is reactive to the class property selected_timer_type. In other words we use a ES6 class (!= React class) to do state management.

The implementation of MultiCreator is not finished and not used in production, so don't be surprised if things don't make sense.

I'll be further developing the app in the next coming days/weeks and I'll keep you updated.