ReactJS: jQuery like components built with Flux

264 views Asked by At

Scenario: I want to extend an existing React component and deliver it as a standalone component.

Let's take for example Facebook's FixedDataTable (https://github.com/facebook/fixed-data-table), add some extra features and wrap it as a re-usable component.

The first extra feature would be "multiple row selection" - demo can be found here http://goo.gl/qRE9eB

What anyone can notice here is that the MovieTable wrapper handles the checked / not checked state of the rows. So, what I'll want to do next is to delegate the responsibility of the state handling to a Flux store (for simplicity, let's consider Facebook Flux implementation https://github.com/facebook/flux). Probably it doesn't make too much sense to do this now, but as the complexity of the MovieTable grows (sorting, infinite scrolling etc.), integrating Flux would be a necessity. According to Flux architecture (Action -> Dispatcher -> Store -> View), _onRowClick and _onCheckAll will trigger actions which will allow the Store to save the state and notify the view that something was changed, in order for the view to re-render the new state of the checkbox.

Let's assume next that I want to bundle the MovieTable view together with its actions / dispatcher / store as a standalone component, so that I could re-use it later. First question:

1) does it make sense to bundle together the view / actions / dispatcher / store as a standalone component? From my point of view, the benefits are clear: the one that uses the component doesn't need to take care of the "internals" of the component (e.g. row selection, infinite scrolling, sorting etc.)

Let's consider that I choose to bundle everything together. The next questions are:

2) How can I get data out of the Store? e.g. some part of the application might need to get all the selected rows from the component's Store

3) How can I trigger actions on the dispatcher of the component? e.g. I want to programmatically check some rows - my first thought is that the client should have access to the actions of the component

4) Given 1), 2) and 3), I want to have a re-usable DataTable component that "feels" like a traditional jQuery component (e.g. jqGrid http://goo.gl/b7jPo3). The ultimate goal would be to combine jQuery like components with React components in the same page, without causing too much pain to the one that mixes these.

1

There are 1 answers

5
Michelle Tilley On

I think it's fine to implement complex libraries with flux (or any other design pattern) under the hood, but that the library should make every effort to hide these complexities from the end-user. For example, a Node.js library might use callbacks, an async control flow library, or promises to manage asynchronous operations inside the library itself, but to allow users to interop with most Node apps, it should at least support callbacks in the public API. (As promises become more first-class in JavaScript, this pattern may shift, but I hope you get my point.)

In React, the least-common-denominator for component-based APIs are props (to provide data, and to provide function references to serve as callbacks). If at all possible, attempt to make your API work using just props.

If, in a very large or complex component, that's just not possible (and I would argue that the component+props strategy can take you a very long way before it really breaks down), it may make sense to expose a more traditional, object/method-based API. However, I would still strive not to expose the flux underpinningsā€”a facade with a method called dataTable.selectRows(rowIndicies) (which delegates to the actions) is easier to understand/remember and is less brittle/resistant to change than dataTable.dispatcher.dispatch(DataTableActions.selectRows(rowIndicies)).


I'm not quite sure I understand the #4 item (maybe it's not really a question?) If I'm already building a React app, I have no desire to expose React components as jQuery plugins, if I'm building a non-React, jQuery app, I don't really have a desire to require React as a dependency just to use a data table.