Giter VIP home page Giter VIP logo

observe-component's People

Contributors

actonw avatar lilactown avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

Forkers

zcgong

observe-component's Issues

ComponentEvent API

It might be more useful to use { type, value } instead of { type, event }. Some events send back a ReactEvent while others send raw values or other object types (e.g. React Native's TextInput onChangeText responds with a string value of the input).

This would be a breaking change, though, so would require a major version increment.

API changes

Proposal 1: observeComponent returns observable

Right now, creating the ObservableComponent and obtaining the observable attached to the component is done in two steps:

// create observable component
const MyComponent = observeComponent('div')('onClick');

// obtain the observable attached to it
const myObs$ = fromComponent(MyComponent);

observeComponent could be changed to instead return both the component we are observing, as well as the observable attached:

const { component, observable } = observeComponent('div')('onClick');

This would remove the need for fromComponent, however it would require users to use object destructuring and renaming:

const {
  component: MyComponent,
  observable: myObs$,
} = observeComponent('div')('onClick');

const {
  component: OtherComponent,
  observable: otherObs$
} = observeComponent('input')('onChange');

It could also be done by returning an array instead of an object to avoid the verbosity of renaming the object properties:

const [MyComponent, myObs$] = observeComponent('div')('onClick');

However, this would be less ergonomic for people who may be utilizing this library without es2015+.

Pros:

  • Reduces API surface (only one function!)
  • Removes the need to mutate the wrapped React component by attaching the observable as a property
  • Removes fromComponent function, which is slightly redundant and potentially confusing to new users.

Cons:

  • Relies on ES2015+ syntax to be really ergonomic
  • Would be a breaking change
  • Loses similarity to obtaining observables from other event-producing objects in most libraries (Rx.Observable.from(), Kefir.fromCallback/fromEvents/fromPoll, etc...)

Support component methods

Currently, observeComponent(SomeComponent) prevents accessing of any static methods on SomeComponent

Named export for requiring RxJS

Have we considered using named exports for specific methods so that we don't immediately require the entire RxJS bundle on behalf of the user (of this library)?

It would mean replacing this:

var Rx = require("rxjs/Rx");
...
subjectFactory: function () { return new Rx.Subject(); },

With this:

var Subject = require("rxjs/Subject").Subject;
require('rxjs/add/operator/filter');
...
subjectFactory: function () { return new Subject(); },

The benefit is that we are no longer pulling in the entire RxJS library for this library to work. But the downside is that the user needs to manually add in their own methods (because the observable passed to them will be "barebones").

For example, the observable the user gets back from fromComponent() will not have methods like .share() or .debounceTime(). They would need to add it themselves explicitly like this:

import 'rxjs/add/operator/share';
import 'rxjs/add/operator/debounceTime';

One option to get around this is to simply provide both options to the user. Maybe something like this:

// Imports the whole RxJS bundle
import { observeComponent, fromComponent } from 'observe-component/rxjs/full';

// Imports only the necessary objects and methods
import { observeComponent, fromComponent } from 'observe-component/rxjs';

The library might get bigger, but this gives the developer much more control if he wants to keep the bundle size small for production

ObservableComponent does not gracefully support dynamic lists of components

Currently, using observe-component, one cannot pass UI state through the stream without manually adding handlers into the view code. E.g.:

const ClickableLi = observeComponent('onClick')(({ name }) => <li>{ name }</li>);

function View() {
  return (
    <ul>
      {['John', 'Will', 'Marie'].map((name) => <ClickableLi name={name} />)}
    </ul>
  )
}

fromComponent(ClickableLi)
  .subscribe((event) => {
    // there is no way to get the UI state (which name was clicked) other than
    // accessing the DOM directly using `event.value.target` 
  });

Currently, the only way to get the desired behavior is by manually calling the event handlers passed to the observed component with the desired data:

const ClickableLi = observeComponent('onClick')(({ name, onClick }) =>
  <li onClick={onClick(name)}>{ name }</li>
);

// ...

fromComponent(ClickableLi)
  .subscribe((event) => {
    console.log(event.value); // "John"
  });

This is very undesirable, as the whole point of the library is to remove the need to deal with event handling in our view code!

A possible change in the API could provide seamless propagation of UI state (props) through the ComponentEvent.

The simplest solution would be to propagate props through an additional field in ComponentEvent:

class ComponentEvent {
  type: string,
  value: React.SyntheticEvent,
  props: any,
};

Although this begs the question why value is named as such, since the point of changing it previously was to reflect the fact that one may want to pass other things besides the synthetic event back...

class ComponentEvent {
  type: string,
  event: React.SyntheticEvent,
  props: any,
};

In theory, this should allow one to capture any necessary UI state through the props of the component being acted on.

Example suggestion with React usage

I had a little bit of trouble getting started in the beginning. I didn't realize that fromComponent and observeComponent were both needed. In any case, I've created the following example for other people who are also using React and RxJS v5 with this library.

@Lokeh feel free to add this example to your docs, and thanks for the library! Please let me know if there can be any improvements to the following code.

import React from 'react';
import { observeComponent, fromComponent } from 'observe-component/rxjs';

// Create the component with the listeners we want
const TextArea = observeComponent('onInput')('textarea');

export default class MyComponent extends React.Component {
  constructor() {
    super();
    this.state = { typing: false };
  }

  componentDidMount() {
    // Create stream for when user is typing
    this.inputEvents$ = fromComponent(TextArea, 'onInput').share();

    // Create stream for when user has been idle for 1 second
    this.idle$ = this.inputEvents$.debounceTime(1000).share();

    // Subscribe to invoke the streams and handle the events
    this.inputEvents$.subscribe(() => this.setState({ typing: true }));
    this.idle$.subscribe(() => this.setState({ typing: false }));
  }

  componentWillUnmount() {
    this.inputEvents$.unsubscribe();
    this.idle$.unsubscribe();
  }

  render() {
    return (
      <div>
        <TextArea cols="30" rows="10" />
        <div>{this.state.typing ? 'User is typing...' : 'User is idle'}</div>
      </div>
    );
  }
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.