Code Monkey home page Code Monkey logo

rel-events's Introduction

rel-events

Build Status Coverage Status

To read the docs, go to our docs folder. :) To see the app demo, go to our codesandbox page!

Welcome to the rel-events github repo!

rel-events is an awesome events library for react. It uses redux behind the scenes to offer a more convenient, simple and relevant API for dealing with data flows.

Basic Usage

Installing

To install rel-events, just run npm i --save rel-events.

If you wish to use Events to make HTTP Requests (which you probably do), there's another step to set things up. Follow our HTTPEvents Guide to have everything ready. :)

With that done, you may start to create some events!

Creating a basic Event

Let's say you want to pass a range of dates from DatePickerComponent to CalendarComponent. Instead of creating actions and reducers, forget everything about redux; create an Event instead.

To do that, you need to initialize a new Event. It's recommended you create it in a new file (events.js).

// on events.js
import { Event } from 'rel-events';

export const ChooseDateRangeEvent = new Event({
  name: 'chooseDateRange',
  manager: {
    initialState: {},
    onDispatch: (state, event) => {
      return {
        ...state,
        startDate: event.startDate,
        endDate: event.endDate,
      }
    }
  }
});

Let's break step-by-step what this code means:

First, you import the Event class from our lib, then instantiate a new event. This Event receives an object with two required keys: name and manager. While name is self-explanatory, manager is not.

For default Events, an Event Manager should have an initialState and implement an onDispatch method, which will be called whenever the event is dispatched. This is the alternative to the reducer part of the default redux flow.

We recommend using classes for your EventManagers as well, since we can decouple Events from their managers.

// on eventManagers.js
export class ChooseDateRangeEventManager {
  initialState = {};

  onDispatch = (state, event) => {
      return {
        ...state,
        startDate: event.startDate,
        endDate: event.endDate,
      }
    }
  }
}

Then:

// on events.js
import { Event } from 'rel-events';
import { ChooseDateRangeEventManager } from './eventManagers.js';

export const ChooseDateRangeEvent = new Event({
  name: 'chooseDateRange',
  manager: new ChooseDateRangeEventManager(),
);

Hooking it up with redux

With the event instantiated, you need to hook it up to redux so it can be dispatched and save data. When creating your root reducer, you should import the Event and initialize its reducers.

// on myAppRootReducers.js
import { combineReducers } from 'redux';
import { combineEventReducers } from 'rel-events';
import { ChooseDateRangeEvent } from './events.js';

// remember to use object spread, so it's set up correctly
export default combineReducers({
  ...combineEventReducers([ ChooseDateRangeEvent ]),
});

Notice the store names and reducers aren't declared anymore; you don't need to. Any Event object will deal with anything and everything redux related. To be able to do that, you only need to hook it to redux as the example above. To see more on how this works, read our how it works docs.

Now you have our Event ready to go! Now, you just need to register it to a Component, which can trigger it and/or listen to it.

Registering components to Events

Let's say you have a component called DatePickerComponent that knows how to render a beautiful date picker. It has a handleDatesChange method to update the state with the new dates.

export default class DatePickerComponent extends React.Component {
  //...
  handleDatesChange = (startDate, endDate) => {
    this.setState({ startDate, endDate });
  }
  //...
}

To be able to send data from this component to the CalendarComponent, you may register both Components to your Event. Whenever you register a Component to an Event, you automatically receive a function to trigger the event as a prop. The function's name is the same as the event name you passed when initializing the event.

import { ChooseDateRangeEvent } from './events.js';

// you won't export the component directly anymore
class DatePickerComponent extends React.Component {
  //...
  handleDatesChange = (startDate, endDate) => {
    // here, the event passing the new dates is triggered
    // after setState is done
    this.setState(
      { startDate, endDate },
      () => this.props.chooseDateRange({ startDate, endDate })
    );
  }
  //...
}

// and here, you register the component to the event.
// since Components are mostly named with CamelCase,
// we preferred to name the key like that as well
export default ChooseDateRangeEvent.register({
  Component: DatePickerComponent,
});

// you may as well register a Component to multiple events, no worries;
// just remember to only export after you're done registering the Component to your events

Then, you may register your CalendarComponent as well, but passing a new props key:

import { ChooseDateRangeEvent } from './events.js';

class CalendarComponent extends React.Component {
  //...
  render(){
    const { startDate, endDate } = this.props;

    return <h1>The dates are: {startDate}, {endDate}</h1>
  }
}

// and here, you get the props from the event
export default ChooseDateRangeEvent.register({
  Component: CalendarComponent,
  props: ['startDate', 'endDate'],
})

And that's it! We still have a lot of other features to discuss, but I'll talk about those later. Before that, let's talk about using events to make HTTP requests.

Contributing

Thanks for wanting to contribute! Please, read our Contributing guide carefully before opening PRs, though. We do enjoy PRs, but any PRs that don't follow our contributing guidelines will probably be rejected :/

Thanks

Thanks for everyone at Labcodes for giving me the structure and time for me to work on this pet project of mine and giving me lots of awesome feedback! Bernardo Fontes, Luan Fonseca, Thulio Philipe, Mariana Bedran, Breno Chamie and Renato Oliveira, I'm really, really grateful for your input! <3

labcodes github banner

rel-events's People

Contributors

dependabot[bot] avatar gsilva49 avatar isabarros avatar lucianoratamero avatar objnamegit avatar poojakhandhadia avatar

Stargazers

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

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

rel-events's Issues

Add app demo

It would be nice to have an app demo, so the users can fiddle around with it!
I'd recommend something like Scrimba to have an interactive guide with all the files, but anything that gives us a proper sandbox would be amazing. :)

Add check to throw error if an Event/HTTPEvent is initialized without args

As suggested by @isabarros :
"(Currently) The error thrown in both scenarios is 'An Event should be initialized with an event name.' which is the first check done in the constructor, you might probably want to add another check prior to that to see if it falls in the empty scenario and throw something like 'An Event should not be initialized without parameters.'

Add FAQ to docs

We need a FAQ page to deal with common misconceptions or comparisons between this lib and other solutions.

I'd recommend at least have a comparison to plain old redux, redux + react-redux-api-tools and useReducer hook.

Add a debounce option to make an Event debounceable

One of the things that frustrate me a lot is that, most of the time, we need to debounce things inside react components before triggering requests.
It would be nice to have something built-in that debounced the 'call' methods (for HTTPEvents) or 'onDispatch' methods (for normal Events). Maybe use lodash's debounce implementation?

Implement structure to support formatters

One of the things I'd really love to have would be to assign functions as formatters to Events.

That would make the whole architecture more flexible, since these would be reusable and because sometimes we want that an Event has different data outputs, but the same manager logic.

Add "Contributing" guide to docs

We just need to add a quick guide on how to contribute (how to install locally, run tests, etc).

I'll be working on that right now :)

Add "How it works" docs

I didn't think the "How it works" docs was essential for the first release, so I left it for later.
I'm assigning this to myself, since, well, I wrote the d**n thing. :x

So yeah, next release.

Add contibuting guide

Currently, we have a link to the contributing guide on the Readme, but it returns a 404.

Add a way to use 'last call arguments' as default arguments when listening to an Event

Most of the time, when listening to an Event, we want to repeat the last call made changing only what the new Event data is passing.

Example, we have a datepicker changing dates and multiple Events listening to the datepicker Event.
Now imagine one of these is a paginated call.
To make things work as expected, we currently need to remove the 'listenTo' for that paginated Event, register the Component that deals with the pagination to the datepicker Event and actively listen to it (on the componentDidUpdate hook), only to pass the correct data when teh date changes.

To solve this, we could have a way to reference the last call args to an Event on the default args declaration for the 'call' method.

Basic Events are not listening to each other

When trying to create two Events that clear two HTTPEvents, I made one Event listen to the other, so that everything is cleared in one go.
The listenTo key did nothing, though. Probably the _chainEvent handler is not being called if the action type is different for base Events.

Revert global threshold for branch code coverage to 100

Since @isabarros has fixed the issue with the branching tests, we can now revert the threshold of branch coverage to 100 again.

To do that, we just need to change the settings inside the package.json file from 95 to 100 and run the tests. If everything goes well, just send the PR to be accepted.

Thanks!

Change the name "manager" to "lifecycle"

One of the things that still seems rough around the edges is the name "manager" when creating an Event.
"Manager" seems too formal and not 100% suited for what it does.
I thought about changing it to "lifecycle" to the 1.0 release.
Any feedbacks?

Solve branch coverage issues on Jest/Coveralls

For some unknown reason (at least to me), even though I've added tests for every single scenario and branching paths, there are still two lines of code that jest/coveralls say they're not covered; both of them are the lines for the initialization of Event and RequestEvent classes.

It made me lower the branch coverage goal to 95%, which is not ideal. :(

Add way for multiple events to consume the same store key

Currently, only Events with the same name would be able to consume the same store key.

That means that we could have a prop conflict if we registered both Events to the same Component, and both Events would trigger each other whenever they're called.

It would be amazing to have this feature, so we could have an Event clear the store of another, for example.

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.