Giter VIP home page Giter VIP logo

fluxible's Introduction

Fluxible Build Status

This repository is the home of Fluxible and related libraries.

For support, please use GitHub Discussions.

Documentation

Please check out the Fluxible package README for documentation.

Development

All code is developed against the latest Node LTS version. This repository leverages npm workspaces for package management.

Publishing

The changesets library publishes packages to the npm registry. Use the following steps to publish a package:

  1. After making changes to a package in your branch, run npx changesets and follow the prompts to choose which package needs to be published and what type of version (i.e., major, minor, patch).
  2. Commit the newly created .changes/<id>.md file to your branch.
  3. Open a PR with your changes.
  4. Once reviewed and merged, the GitHub Actions publish job will run the changesets action and open a new PR with package.json and CHANGELOG.md changes for the packages chosen to publish.
  5. Merge this PR when a release is needed.

License

This software is free to use under the Yahoo Inc. BSD license. See the LICENSE file for license text and copyright information.

fluxible's People

Contributors

alexaivars avatar ali1k avatar andrewraycode avatar ash14 avatar cesarandreu avatar dependabot-preview[bot] avatar dependabot[bot] avatar escalona avatar geekyme avatar geta6 avatar gingur avatar gpbl avatar greenkeeper[bot] avatar greenkeeperio-bot avatar jedireza avatar kaesonho avatar knutties avatar koulmomo avatar lingyan avatar localnerve avatar lucianlature avatar malaman avatar mbfisher avatar mridgway avatar pablopalacios avatar redonkulus avatar retlawrose avatar snyamathi avatar tom76kimo avatar vijar 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  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  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  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  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

fluxible's Issues

how to load actions after dynamic page routing?

I could not figure out how to load an action after using the router!?
I tried to use the router plugin to route my dynamic pages. For example /deck/12 should first render the Deck component and then should execute an action loadDeck(12) which feeds the content for the Deck component. I tried the following solutions but didn't succeed:

  1. I can call an action within the application store (after routing) which would break the flux unidirectional way! so I prevented that.
  2. I tried to use componentWillMount() before the Deck is rendered to execute loadDeck() action. The problem is that it breaks the server-side rendering and loads the content only on the client.

Could you advise me what is the best way to execute an action after routing? my action might need to call a Web API as well...

Dehydrating stores with routr

I'm new to fluxible and I'm trying to setup my first app with it, so I apologize in advance for the silly question.

I configured my routes to execute an action, which should load an array of photos before rendering the home page:

// routes.js
var getPhotos = require('../actions/getPhotos');
var routes = {
  home: {
    path: '/', method: 'get', page: 'home', label: 'Home',
    action: function(context, payload, done) {
      // will add an array of photos to the PhotosStore
      context.executeAction(getPhotos, {}, done);
    }
}

On the server I'm dehydrating data as in the examples:

var context = app.createContext();
var actionContext = context.getActionContext();
actionContext.executeAction(navigateAction, { url: req.url },function (err) {
    var state = 'window.App=' + serialize(app.dehydrate(context), 'App'); // etc

Now the dehydrated state does not contain the PhotosStore, only the ApplicationStore. The component, rendered server-side, loads the photos regularly.

Clearly I'm missing some base concept: how to dehydrate the other stores as well?

FluxibleMixin & Contexts issues since 0.3.x

Hi,

More a "how to" issue. I don't understand how exactly I have to use FluxibleMixin and FluxibleComponent to propagate the context in all the descendant views.

Here comes a lot of code, but that's for illustrating my use case and maybe it could be useful to some others.

Please note that I use Fluxible only client-side for this project.

Here is my main app:

'use strict';

var React = require('react');
var Fluxible = require('fluxible');
var EntryPointController = require('./entrypoint/EntryPointController.react');
var EntryPointStore = require('./entrypoint/EntryPointStore');
var CreationStore = require('./creation/CreationStore');
var PhotosStore = require('./photos/PhotosStore');

var app = new Fluxible({
    component: React.createFactory(EntryPointController)
});

app.registerStore(EntryPointStore);
app.registerStore(CreationStore);
app.registerStore(PhotosStore);

var context = app.createContext();

React.render(
    app.getComponent()({
        context: context.getComponentContext()
    }),
    document.getElementById('app')
);

EntryPointController is basically a page asking a question where "Yes" render a Controller (creation), and "No" render another one (simple album). Here is a simplified version:

var EntryPointController = React.createClass({

    mixins: [FluxibleMixin],

    statics: {
        storeListeners: [EntryPointStore]
    },

    getInitialState: function() {
        return this.getState();
    },

    getState: function() {
        this.store = this.getStore(EntryPointStore);
        return {
            creationType: this.store.getCreationType()
        };
    },

    // UI event handlers
    createCreation: function() {
        this.executeAction(EntryPointActions.createCreation, {});
    },

    createAlbum: function() {
        this.executeAction(EntryPointActions.createAlbum, {});
    },

    render: function() {

        if ('creation' === this.state.creationType) {
            return (
                <CreationController/>
            );
        }

        if ('album' === this.state.creationType) {
            // TODO
            return (
                <AlbumController/>
            );
        }

        return (
            <div>
                <p className="question">
                    Would you like to introduce one or your creation{'\u003F'}
                </p>

                <button type="button" onClick={this.createCreation}>Yes!</button>
                <button type="button" onClick={this.createAlbum}>No</button>
            </div>
        );
    },

    onChange: function () {
        this.setState(this.getState());
    }

});

module.exports = EntryPointController;

Now, CreationController is a multiple-step form, each step being a simple view (meaning it doesn't dispatch any action, nor manage the global state of the form). All steps relay on the controller regarding the global state management (in CreateStore).

But in one of these views, I render a PhotosController, which is basically a full-featured uploader and image manager, and it has its own store and own state. And that's where I have an issue. I can't seem to be able to propagate the context to it, and I don't understand why.

In my CreationStepThree view, I added the FluxibleMixin so the component gets the context. And it does, but I'm not sure why, it doesn't propagate it to the underlaying PhotosController component.

var CreationStepThree = React.createClass({

    mixins: [FluxibleMixin],

    propTypes: {
        formData: React.PropTypes.object.isRequired,
        onSubmit: React.PropTypes.func.isRequired,
        onBack:   React.PropTypes.func.isRequired
    },

    goBack: function(e) {
        e.preventDefault();
        this.props.onBack();
    },

    handleSubmit: function(e) {
        e.preventDefault();
        // todo
        this.props.onSubmit({});
    },

    render: function() {
        var formData = this.props.formData;

        return (
            <PhotosController onFormSubmit={this.handleSubmit} onGoBack={this.goBack} />
        );
    }

});

module.exports = CreationStepThree;

PhotosController, in part:

var PhotosController = React.createClass({

    mixins: [FluxibleMixin],

    propTypes: {
        onFormSubmit: React.PropTypes.func.isRequired,
        onGoBack:     React.PropTypes.func.isRequired
    },

    statics: {
        storeListeners: [PhotosStore]
    },

    getInitialState: function() {
        return this.getState();
    },

    getState: function() {
        this.store = this.getStore(PhotosStore);
        return {
            photos:         this.store.getPhotos(),
            selectedPhotos: this.store.getSelectedPhotos()
        };
    },

    handleFileAdded: function(photo) {
        var id = uuid.v4();
        this.executeAction(PhotosActions.addPhoto, {
            id:     id,
            name:   photo.name,
            type:   photo.type,
            status: photo.status,
            size:   photo.size
        });

        photo.id = id;
    },

    // a bunch of other handling methods like handleFileAdded
    // which dispatch PhotosActions

    render: function() {
        return (
            <div>
                  ...... a lot of stuff here
            </div>
        );
    },

    onChange: function () {
        this.setState(this.getState());
    }

});

module.exports = PhotosController;

Here is the CreationController:

var CreationController = React.createClass({

    mixins: [FluxibleMixin],

    statics: {
        storeListeners: [CreationStore]
    },

    getInitialState: function() {
        return this.getState();
    },

    getState: function() {
        this.store = this.getStore(CreationStore);
        return {
            formData:     this.store.getFormData(),
            currentStep: this.store.getCurrentStep()
        };
    },

    goBack: function() {
        this.executeAction(CreationActions.goBack, {});
    },

    submitStepOne: function(data) {
        this.executeAction(CreationActions.submitStepOne, data);
    },

    submitStepTwo: function(data) {
        this.executeAction(CreationActions.submitStepTwo, data);
    },

    submitStepThree: function(data) {
        this.executeAction(CreationActions.submitStepThree, data);
    },

    render: function() {
        var form;

        switch(this.state.currentStep) {
            case 1:
                return (
                    <CreationStepOne
                        formData={this.state.formData}
                        onSubmit={this.submitStepOne}
                        onBack={this.goBack}
                    />
                );
                break;

            case 2:
                return (
                    <CreationStepTwo
                        formData={this.state.formData}
                        onSubmit={this.submitStepTwo}
                        onBack={this.goBack}
                    />
                );
                break;

            case 3:
                return (
                    <CreationStepThree
                        formData={this.state.formData}
                        onSubmit={this.submitStepThree}
                        onBack={this.goBack}
                    />
                );
                break;

            default:
            // todo: handle this case
        }

        return (
            <div>
            </div>
        );

    },

    onChange: function () {
        this.setState(this.getState());
    }

});

module.exports = CreationController;

Any idea ? What am I missing here ? :p
I didn't have any trouble before upgrading to React 0.13.1 & Fluxible 0.3.x.

Also, it may not be related at all, but I now get the following warnings in the console (and not just for CreateStepThree, for all of them):

Warning: owner-based and parent-based contexts differ (values: `function componentExecuteAction(action, payload) {
            self.executeAction(action, payload, function actionHandlerWrapper(err) {
                var noop = function () {};
                self.executeAction(self._app._componentActionHandler, { err: err }, noop);
            });
        }` vs `undefined`) for key (executeAction) while mounting CreateStepThree (see: http://fb.me/react-context-by-parent)
Warning: owner-based and parent-based contexts differ (values: `function () { [native code] }` vs `undefined`) for key (getStore) while mounting CreateStepThree (see: http://fb.me/react-context-by-parent)

Is it possible to execute an action from within my Stores?

Building off your examples I'm trying to execute an action from within my a Store. I'm handling the router published 'CHANGE_ROUTE_START' event and want to execute a new action to then fetch some data.

I found the 'getContext' method of the dispatch that is passed as the first argument to the Store but it returns an empty Object {}. Is it possibly a problem on my end or is there another way to get the app context so that I can call context.executeAction() within my store.

The reason I'm doing this is I do not want to optimistically render my new component in response 'CHANGE_ROUTE_START' but want to fetch data to populate the Store and then render the complete component.

Awesome work BTW on fluxible and the plugins.

react-dependency fails in older npm

hi,

if you use node-0.10, and the npm bundled with it, then this fails:

npm install [email protected] [email protected]

npm ERR! peerinvalid The package react does not satisfy its siblings' peerDependencies requirements!
npm ERR! peerinvalid Peer [email protected] wants react@>=0.12.0 <=0.13.x

on node-0.12 it works.

im guessing this is a npm bug that was fixed in npm/node-semver@c835c1d .

but, considering node-0.10 is still used, could fluxible perhaps use a different "backward" compatible dependency-version?

im not sure how exactly this works, but perhaps instead of "<=0.13.x" go with "<0.14" or something?

Data dependency and server side rendering

(sorry for today's spam, I've been trying to get a full functional app using flexible for the past few days.)

Questions:

  • how do you deal with multiple requests with fluxible to perform a complete a full server side rendering?
  • how do you deal with global context (for instance: you have some user information you need to pass down to different stores so they can send the, let's say, user session to the api.)

Let's say you have the following chat application:

└── components
    β”œβ”€β”€ form.js
    β”œβ”€β”€ index.js
    β”œβ”€β”€ last_messages.js
    β”œβ”€β”€ thread.js
    └── sidebar.js
  • Index: is performing an action to get the user informations.
  • Sidebar: needs to have the list of channels to be rendered.
  • Last messages: needs to have the list of the last messages that have been sent in all channels combined
  • Form: need to have additional user information to display (for instance) their logo.
  • Thread: need an that is provided from the sidebar (or the url) to be rendered.

The chat example shows that the data is being fetched within server.js, but what happens when this request is actually triggered by a component?

And more importantly, what happens when you have within one component, two components that requires data from different sources?

Advices would be much appreciated :)

Client Only Actions - Stream to Server

I just began using the fluxible project, and I'm very impressed. Prior to this project, I created my own flux framework; however, it wasn't isomorphic, and I'm very impressed with the way this project works isomorphically.

However, I've come across a situation where I want to allow the user to record some audio using the new HTML5 audio capabilities, and obviously this is something that should only be triggered client-side. My initial thoughts were to create an action that is only invoked client-side; however, something feels dirty regarding this approach.

Do you have any suggestions for handing this differently?

Delete store content if no longer needed

Lets say there is a page with a /products link that populates a product store with a ton of data.

If someone then clicks on a link to a totally unrelated content e.g. "/about" one would
possibly like to reset/delete the content of the product-store to reduce the memory pressure.

So what is the appropriate way to delete store entries in an automated way?

One way I can think of is to allow a store to delete its content as
soon as the last listener is detached... this should be configurable
but disabled as a default I think.

How do you handle store data that is not required anymore?

Namespacing plugins

Currently plugins add functionality to the root of context. This makes it easy for plugins to pollute context or collide features with one another.

Also in larger apps it can get hard to know which plugin is responsible for a specific piece of functionality. I'd like to see plugin functionality to be namespaced. context.pluginName.someFeature(...) as an example.

Plugin names should be unique and we should throw during app.plug({ ... }) if a a plugin with the same name has already been registered.

If you take a look at [email protected], they're kind of following a similar idea in that context.router contains all their functionality.

Improve "require('fluxible-app/utils/createStore')" and also "BaseStore"?

I suggest to improve the way the user has to import the "createStore" and "BaseStore" utilities. Because the current approach seems like we are requiring a "private" file instead of something well documented and ready for use.

I could provide a PR (if you want). My approach would be just updating the "Helper Utilities" section in the README.md and the /index.js to add the following:

module.exports.createStore = require('./utils/createStore');
module.exports.BaseStore = require('./utils/BaseStore');

React-router and actions

I'm trying to do some test with fluxible and react-router and I can't figure how react-router and flux actions work together.

If I use fluxible without react-router (with the recomended router). A route is associated to an action. Action who can load the needed data to populate some store. And then these data is used to render the app. This is simple and works well.

Now I'm trying to do the same with react-router, but as we associate a route with a component. I do not see where call my action to prepare the data in my store.

For now, I execute the action in the getInitialState method of my component:

    getInitialState: function () {
        this.executeAction(hotelListUpdate, {/* ... */});

        return this.getState();
    },

It's work, but trigger two render of the component on the screen: the first without the data, the second with.

Have you any clue?

Release 0.2.1 with FluxibleMixin export

Would be nice to release this: 9d1f17c

I actually considered making the suggestion for adding a Mixin alias as FluxibleMixin when I tried out 0.2.0, but I thought it would be such a minor thing that it wasn't worth it. But seeing as it's already been merged, it'd be great if it were released.

Basically, i means I can replace this:

var {Mixin: FluxibleMixin} = require('fluxible');

With this:

var {FluxibleMixin} = require('fluxible');

Using constants for handlers

If I were to create a simple store:

var AuthenticationStore = createStore({
    storeName: 'AuthenticationStore',
    handlers: {

    }
});

And want to add a handler, that's easy enough to declare:

handlers: {
    'SIGNOUT': 'handleSignout'
}

But, what I don't see a way to do is to use a "constant" value as the name of the action being handled. I want to declare them in advance and use them consistently and safely across my code base rather than relying on me typing string values consistently:

var AuthActions = {
    SIGNOUT: 'SIGNOUT';
};

Then, I could do something like (inspired by Fluxxor), where there is an initialization function that allows the actions/handlers to be bound (here, they're bound as KV pairs):

initialize: function() {        
    this.bindActions(
      AuthActions.SIGNOUT, this.handleSignout
    );
}

Koa and fluxible-app

I like Koa. A lot. However fluxible in its current form is defying my attempts to promisify it and make it more *generator friendly. Usually I've been able to track down a koa-ified module to replace what I'd normally use in Express, and if that failed, Bluebird saved the day.

I'm running into one particular issue, and that's with getActionContext().executeAction().

I've tried promisifying executeAction and running it with a payload, however when the action runs its payload is undefined.

If anyone has guidance for how to properly use fluxible-app in generators (with yield, etc), or if it's possible, I'm eager to learn.

Canceling a router action

I'm very happy I've spent some time with fluxible, I'm liking it a lot πŸ‘

I have a last problem (i hope). This route is fetching some data before calling the done callback:

// routes.js
var getBooks = require('../actions/getBooks');
var routes = {
  books: {
    path: '/books',
    page: 'books',
    action: function(context, payload, done) {
       // fetch the books from a REST API
       context.executeAction(getBooks, {}, done);
    }
  }
}

When the user visits another route before the call ends (e.g. clicking a NavLink), he will jump back to the this route as soon as the "old" action is finished.

How could I prevent this behaviour? Or is the action expected to be async?

Provide props from top level component (FluxibleComponent?)

I'm interested in seeing a top level component that provides props populated from stores to child components.

Example before/after usage.

// this is how you work with a store using FluxibleMixin directly
const ProductList = React.createClass({

  mixins: [FluxibleMixin],

  statics: {
    storeListeners: {
      _onChange: [ProductsStore]
    }
  },

  getInitialState() {
    return {
      products: this.getStore(ProductsStore).getProducts()
    }
  },

  _onChange() {
    let products = this.getStore(ProductsStore).getProducts();
    this.setState({products: products});
  },

  render() {
    let products = this.state.products || [];
    let list = products.map((d, i)=>{
      return (<li key={i}>{d.title}</li>);
    });
    return (
      <div>
        <h2>products</h2>
        <ul>
          {list}
        </ul>
      </div>
    );
  }
});

const ProductPage = React.createClass({
  render() {
    return (
      <ProductList/>
    );
  }
});


// using FluxComponent
// queries: provide a list of store to props mappings, could also provide other meta information
// Component's props auto-update on change
// Now the Components can be interrogated for information
// Ask them questions like:
//   What stores do my children access?
//   Are those stores 'initialized'?

const ProductList = React.createClass({

  statics: {
    queries: [{
      store: ProductsStore,
      map: store =>({
        products: store.getProducts()
      })
    }]
  },

  render() {
    let products = this.props.products || [];
    let list = products.map((d, i)=>{
      return (<li key={i}>{d.title}</li>);
    });
    return (
      <div>
        <h2>products</h2>
        <ul>
          {list}
        </ul>
      </div>
    );
  }
});

const ProductPage = React.createClass({
  render() {
    return (
      <FluxComponent>
        <ProductList/>
      </FluxComponent>
    );
  }
});

Here is an initial spike of such a component.

import React from 'react';
import assign from 'object-assign';
import { FluxibleMixin } from 'fluxible';

const FluxComponent = React.createClass({

  mixins: [FluxibleMixin],

  componentDidMount(){
    this.listeners = [];

    React.Children.forEach(this.props.children, child=>{
      child.type.queries.forEach(query=>{
        this._registerListener({
          store: this.getStore(query.store),
          map: query.map,
          handler: this._updateState
        });
      });
    });

    this._updateState();
  },

  componentWillUnmount() {
    this.listeners.forEach(listener=>{
        listener.store.removeChangeListener(listener.handler);
    });
    this.listeners = [];
  },

  _registerListener(listener){
    this.listeners.push(listener);
    listener.store.addChangeListener(listener.handler);
  },

  _updateState(){
    var state = this._getStoreState();
    this.setState(state);
  },

  _getStoreState(){
    return this.listeners.reduce(
      (result, l) =>{
        return assign(result, l.map(l.store));
      }, {}
    );
  },

  getChildProps(){
    return assign(
      {},
      this.state,
      this.getChildContext()
    );
  },

  render(){
    return React.addons.cloneWithProps(this.props.children, this.getChildProps());
  }
});

export default FluxComponent;

question: managing UI state in a fluxible implementation

Hello, I want to seek your advice on managing UI state in a flux architecture / fluxible app.

From my understanding, there are 3 kinds of state:

  1. Router state - This is handled pretty well by React-router, mapping components to different urls.
  2. Persistent state - Getting a list of documents, etc. Fluxible stores and fetchr work well to populate and sync persistent state between the browser and server.
  3. UI state - Things like opening and closing a modal.

After reading http://www.thomasboyt.com/2014/09/15/no-fit-state.html, I am curious how do we fit (3) in the context of a flux architecture where actions are designed to be fire-and-forget ?

Perhaps we have a use case like this:

  1. User hits a 'Create' button, it opens up a modal for user to fill in some data.
  2. After filling in the data and hitting submit, a loading icon appears and the submit button is disabled / muted.
  3. On error, the loading icon disappears, the submit button is enabled, and error messages are being displayed in the modal form (still open).
  4. On success, the loading icon disappears, the form is cleared, and a success message is being displayed in the modal form, which will close itself in 3 seconds and redirect to another page.

In a traditional web app using jquery or some other MVC framework, we will simply rely on ajax calls made by a view and listen to its callback to alter UI state. However this doesn't appear very uni-directional unlike in a flux implementation.

But in a flux implementation, how do we do this?

Do we move UI state into flux stores ? Or do we do something else?

Thanks :)

Error: FluxibleMixin.getStore() is not a function

I'm making a demo app for my company with React, Fluxible and React Router.

I try to use the FluxibleMixin.getStore() method in my React component. And I'm getting an error:

TypeError: Property 'getStore' of object #<Object> is not a function
    at FluxibleMixin.getStore (/workspace/poc-micro-react-router/node_modules/fluxible/mixins/FluxibleMixin.js:86:37)
    at React.createClass.getStateFromStore (/workspace/poc-micro-react-router/src/App.jsx:139:33)
    at React.createClass.getInitialState (/workspace/poc-micro-react-router/src/App.jsx:133:21)
    at ReactCompositeComponentMixin.mountComponent (/workspace/poc-micro-react-router/node_modules/react/lib/ReactCompositeComponent.js:781:48)
    at wrapper [as mountComponent] (/workspace/poc-micro-react-router/node_modules/react/lib/ReactPerf.js:50:21)
    at ReactCompositeComponentMixin.mountComponent (/workspace/poc-micro-react-router/node_modules/react/lib/ReactCompositeComponent.js:808:44)
    at wrapper [as mountComponent] (/workspace/poc-micro-react-router/node_modules/react/lib/ReactPerf.js:50:21)
    at ReactDOMComponent.ReactMultiChild.Mixin.mountChildren (/workspace/poc-micro-react-router/node_modules/react/lib/ReactMultiChild.js:195:42)
    at ReactDOMComponent.Mixin._createContentMarkup (/workspace/poc-micro-react-router/node_modules/react/lib/ReactDOMComponent.js:260:32)
    at ReactDOMComponent.Mixin.mountComponent (/workspace/poc-micro-react-router/node_modules/react/lib/ReactDOMComponent.js:182:14)

I've made a simple node app to reproduce the error: https://github.com/Spy-Seth/poc-micro-react-router.

The application have three routes defined: two static and one dynamic.
All this routes are inside a root route node who manage the layout of the app.
The layout is linked to a store and everything work fine with the simple route: $ curl -i http://localhost:3000/about.

But if I try to access to the $ curl -i http://localhost:3000/message/51 route, the ReadMessage component fail to access to it store.

The FluxibleMixin context seem to be incorrectly initialized. The context.getStore attribute exist, but is value is NULL (

storeInstance = context.getStore(store);
). Another thing, before the fail of rendering the ReadMessage component, the Application component is correctly render: the getStore call works.

Do I do something wrong ? or this is a bug ?

using data from http request

I'm using the react-router example with express as a server, and in order to render the page, I need to grab a header from the incoming HTTP request and supply it.

To do this, I execute an action first that puts some data in a store, and then I render the React router inside the callback, so when the router is rendered, it has access to that data.

I'm wondering if this is actually a safe operation, and whether there are any side effects I'm unaware of? Or is there a better way to do this entirely?

server.use(function(req, res, next){
  var context = app.createContext();
  var token = req.cookies.token || "";

  var router = Router.create({
    routes: app.getComponent(),
    location: req.path,
    transitionContext: context
  });

  context.executeAction(setToken, {token:token}, function(){
    router.run(function (Handler, state){
      var exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';

      var Component = React.createFactory(Handler);
      var html = React.renderToStaticMarkup(HtmlComponent({
          state: exposed,
          markup: React.renderToString(Component({context:context.getComponentContext()})),
          context: context.getComponentContext()
      }));

      res.send("<!doctype html>" + html);
    });
  });

});

The setToken action just dispatches an event that makes a store I have set a field to the provided value.

client specific javascript (jquery plugins, etc.)

Hi,

how do you handle javascript, that should only run on the client?
E.g. a jQuery plugin, that has a dependency on the scroll position.

It doesn't make any sense to render this on the client (and raises an other problem, requiring bower components in node).

How do you guys handle that?

Best,
Sebastian

Add tests to examples

What is the best approach/tool to test isomorphic fluxible-app applications? do you recommend Jest?
Would be great if you added some tests to your examples...

Remove getChildContext from FluxibleMixin

FluxibleComponent should be used for setting the context for the application instead of using the mixin. FluxibleMixin would then only be a helper for setting contextTypes and store listening.

yo generator won't build a 3rd party jsx component but will build with regular webpack

I have been trying to get react-autcomplete installed in a yo fluxible project.

React-autocomplete is uses the .js extension so I changed the loader to

 40                 },
 41                 module: {
 42                     loaders: [
 43                         { test: /\.css$/, loader: 'style!css' },
 44                         { test: /\.jsx?$/, loader: 'jsx-loader' },
 45                         { test: /\.json$/, loader: 'json-loader'}
 46                     ]
 47                 },

Whenever I do this I get

[nodemon] starting `node ./server.js`
 70% 20/20 build modules
/Users/tlaurent/dev/test/node_modules/react-autocomplete/lib/combobox.js:358
      <div className={this.getClassName()}>
      ^
SyntaxError: Unexpected token <
    at Module._compile (module.js:439:25)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/Users/tlaurent/dev/test/node_modules/react-autocomplete/lib/main.js:2:13)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
[nodemon] app crashed - waiting for file changes before starting...

Routing + Fetch Data architecture

Howdy,
I am using fluxible-app together with flux-router-plugin and historyWithHash util. Each route is bound to the react component that displays the dynamic data the come from server.
I created the actions that reads the data from server and call the context.disptach once the response is received, for example:

var getCustomers =  function(context, payload, done){
            context.dataProvider().read('customers', {}, {}, function (err, customers) {
                context.dispatch('GET_DATA_START');
                if (err) {
                    context.dispatch('ERROR_OCCURED', err);
                }
                else {
                    context.dispatch('RECEIVE_CUSTOMERS', customers);
                }
                context.dispatch('GET_DATA_END');
                done();
            });
}

CustomersStore handles the RECEIVE_CUSTOMERS event and emits the changes that intercepted by the Customers component:

var CustomersStore = createStore({
    storeName: 'CustomersStore',
    handlers: {
        'RECEIVE_CUSTOMERS' : 'updateCustomersList'
    },
    initialize: function () {
        this.customersList = [];
    },
    updateCustomersList: function (customersList) {
        this.customersList = customersList;
        this.emitChange();
    },
    getState: function () {
        return {
            customersList: this.customersList
        };
    }
});

var CustomersList = React.createClass({
    mixins : [StoreMixin],
    statics: {
        storeListeners: [CustomersStore]
    },
    getInitialState : function() {
        return this.getStore(CustomersStore).getState();
    },
    onChange: function () {
        var state = this.getStore(CustomersStore).getState();
        this.setState(state);
    },
    render : function(){
        var customersTableBody = this.state.customersList.map(function(customer){
            return(
              <tr>
                  <td>{customer.Name.Name}</td>
                  <td>{customer.Company}</td>
              </tr>
            );
        });
        return(
            <table className='table'>
                <thead>
                    <tr>
                        <th>Name</th>
                        <th>Company</th>
                    </tr>
                </thead>
                <tbody>
                    {customersTableBody}
                </tbody>
            </table>
        );
    }
});

Obviously I want to invoke "getCustomers" action when CustomersList component is loaded(when the route is visited), and I am looking for the best way to do that. In addition I plan to intercept GET_DATA_START and GET_DATA_END in order to show/hide the loading indicator.
So far I have several of options:

  1. Call getCustomers action in corresponding route's action function
  2. Call the same in componentDidMount of CustomersList
  3. Call the same in componentWillMount of CustomersList

Do you have any ideas? What would be the best option? Currently I am inclining towards option#3.

Promise in context.dispatch

I am not sure if this is a fluxible thing or a React issue, but on my initial server-rendered view, if I have a synchronous method in the action, the data propagates to the store and gets de-hyrdated-

'use strict';
var debug = require('debug')('koaReact:loadPageAction');

module.exports = function( context, payload, done ) {
    context.dispatch('LOAD_CAMPAIGNS_START');
    context.dispatch('LOAD_CAMPAIGNS', [{name:"test"}]);
    context.dispatch('LOAD_CAMPAIGNS_END');
    done();
};

However, if I use a function that returns a promise, then the data never gets propagated and then de-hyrdated into the state.

'use strict';
var debug = require('debug')('koaReact:loadPageAction');
var campaignsDal = require("../services/campaigns");

module.exports = function( context, payload, done ) {
    context.dispatch('LOAD_CAMPAIGNS_START');
    campaignsDal.query({}).then(function( result ) {
        context.dispatch('LOAD_CAMPAIGNS', result.toJSON());
        context.dispatch('LOAD_CAMPAIGNS_END');
        done();
    });
};

Is this a problem because of the promise? I am using Koa.js, so I am not sure if the promise is causing the view to be served before the promise is resolved?

best way to combine flux with Websockets

I would like to spread changes in stores to all the clients who are watching the affected component. Do you have any suggestions for that? where to add Websockets in Fluxible architecture?

appComponent and React.createFactory

I've recently updated from 0.1.5 and received a strange error message from React, specifically ReactClass#createClass:

Uncaught TypeError: Cannot read property '__reactAutoBindMap' of null

I fixed this by wrapping my appComponent in React.createFactory:

var App = require('App.jsx');
var app = new Fluxible({
    component: React.createFactory(App)
});

I have no idea why it didn't work nor why it now does! Do you understand what's happening? Have you had any other reports of this?

M

Question: What's the recommended way to store cookie?

Since fetchr is a RESTful API, which should be stateless, so does handling cookie at the client side makes sense?

Also since it's a isomorphic JS app, reading cookie at the server side to dictate the user state also make sense right?

Just want to get these two questions out of my head before I move forward with this approach.

Thanks!
Jerome

Automatic component inclusion

(disclaimer, new to fluxible as most of us probably are.)

If you think about productivity, you think on how much code you can reuse. One the bottleneck that appears quickly as you build a reactjs application is the overload of "require".

Since fuxible-app is acting as an application, it would be convenient if the app was aware of all the different components it contains. For now, I just have a quick dirty fix: I have a view.js file that contains all the references to all my views (components).

In ReactJs, the code looks as following:

render: function() {
    return (<view.ViewName />);
}

It saves a lot of time (you never need to worry about adding a require or removing them – it also simplifies your tree dependency - all views are included on a top level, then they can all start using each other.)

If you think that's a good idea, I would be curious to know what would be the best approach to integrate this with Fluxible.

Wait to render component until data is fetched

I'd like to be able to show a loader in response to an action while data is fetched and wait for the response to render a component. This is a hot topic over in the react-router repo. Have you guys talked about this? Is there a solution currently?

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.