2

I am new in ReactJS and "reactive programming". I tried to create a dispatcher, action and store according to this project, but I don't know how to pass data to component.

In this example it doesn't work.

var data = [1, 2, 3, 4, 5];

var AppDispatcher = Kefir.emitter();

function DataActions() {
    this.getAllData = function () {
        AppDispatcher.emit({
            actionType: "GET_ALL"
        });
    };
}

var Actions = new DataActions();

var getAllDataActionsStream = AppDispatcher.filter(function (action) {
    return action.actionType === "GET_ALL";
}).map(function (action) {
    return function (data) {
        return data;
    };
});

var dataStream = Kefir.merge([getAllDataActionsStream]).scan(function (prevData, modificationFunc) {
    return modificationFunc(prevData);
}, {});

var Content = React.createClass({
    getInitialState: function() {
        this.onDataChange = this.onDataChange.bind(this);
        return {componentData: []};
    },
    componentDidMount: function() {
        dataStream.onValue(this.onDataChange);
    },
    componentWillMount: function(){
        dataStream.offValue(this.onDataChange);
        console.log(Actions.getAllData());
    },
    onDataChange(newData) {
        this.setState({componentData: newData});
    },
    render: function() {
        console.log(this.state);
        var list = this.state.componentData.map(function (item, i) {
            return (
                <li key={i}>{item}</li>
            );
        });

        return <ul>{list}</ul>;
    }
});

React.render(<Content />, document.getElementById('container'));
MoeSattler
  • 6,684
  • 6
  • 24
  • 44
Matt
  • 8,195
  • 31
  • 115
  • 225
  • Can you check via debugger or console log if the data gets lost on it's way from the actions to Kefir or from Kefir to the component? – MoeSattler Sep 05 '15 at 09:49
  • @Moezalez they are lost from actions to Kefir. 'AppDispatcher' doesn't emit the action. https://jsfiddle.net/69z2wepo/15496/ – Matt Sep 09 '15 at 07:21

2 Answers2

1

I believe the issue is that you're using ES6 syntax (which is what the example was written in... notice the Readme). You'll need to either use a transpiler like Babel or convert your method(param => console.log(param)) syntax into normal JS (ie, method(function(param) { console.log(param) });).

BradByte
  • 11,015
  • 2
  • 37
  • 41
1

Before I begin to answer in length I want to answer this part up front:

but I don't know how to pass data to component.

In the example you linked the author passes in the Todos into the main component using React's props, not with an action. So that is the approach I take in my example as well.

Now here is my example. I highly reccommend looking at the example and reading along to what I've written below.

var data = [ 1, 2, 3, 4, 5 ];

// This will now log all events of the AppDispatcher in the console with the prefix 'Kefer: '
var AppDispatcher = Kefir.emitter().log("Kefir: ");

function DataActions() {

    // Our application has an action of emitting a random number.
    this.emitNumber = function() {
        AppDispatcher.emit({
            actionType: "EMIT_NUMBER"
        })
    };
}

var Actions = new DataActions();

var emitNumberActionStream = AppDispatcher
        .filter(function(action) {
            return action.actionType === "EMIT_NUMBER";
        })
        .map(function(action) {
            console.log("EMIT_NUMBER ACTION OCCURRED!!");
            return Math.floor(Math.random() * (10)) + 1;
        });

// Only one stream, no need to merge right now.
//var dataStream = Kefir.merge([ getAllDataActionsStream ]);


var Content = React.createClass({
            getInitialState:   function() {

                // Set initial componentData using the data passed into this component's via props
                return { componentData: this.props.data };
            },
            componentDidMount: function() {

                // On each emitted value run the this.onDataChange function
                emitNumberActionStream.onValue(this.onDataChange);

                // Every second emit a number using the Actions we created earlier
                setInterval(function() {
                    Actions.emitNumber();
                }, 1000);
            },
            onDataChange:      function(emittedNumber) {

                console.log('state on change:', this.state);

                // Update the state by appending the emitted number to the current state's componentData
                this.setState({ componentData: this.state.componentData.concat([emittedNumber])});
                console.log('updated state: ', this.state);
                console.log('-----------------');
            },
            render:            function() {
                console.log('RENDER AGAIN!');

                var list = this.state.componentData.map(function(item, i) {
                    return (
                            <li key={i}>{item}</li>
                    );
                });

                return <ul>{list}</ul>;
            }
        })
        ;

// Pass in initial data using props 'data={data}'
React.render(<Content data={data}/>, document.getElementById('container'));

I modified the example you gave that wasn't working so that it works and makes a little more sense (hopefully).

The Actions and Stores work like this:

Actions:

  • Request a number be emitted

Stores

  • Listen for "EMIT_NUMBER" actions and emit a random number

And the actual component runs like this:

  1. It gets the initial 5 numbers passed into the component via props.
  2. Once mounted it begins listening to the store and creates a setInterval that calls the action dispatcher's emitNumber() action. The interval is to show the reactivity at work, you could imagine that there was a button to press that would call emitNumber() instead.
  3. The store observes the action dispatcher emit "EMIT_NUMBER" and emits a number.
  4. The component observes the store emitted a number and updates the component's state.
  5. The component observes that its state has changed and it rerenders.
Sam
  • 118
  • 6
  • Thank you for your answer Sam. Let me ask you one thing. If you want to emit action in `getInitialState ` function, why it doesn't work? https://jsfiddle.net/zjcdsd84/6/ – Matt Sep 10 '15 at 12:00
  • 1
    The emit action is working in that example. You are trying to capture the emitted number with `var number = Actions.emitNumber();` but `.emitNumber()` doesn't return anything, it just tells the emitter to emit an event. To capture the number you need to subscribe to the `emitNumberActionStream` [using any of kefir's ways](http://rpominov.github.io/kefir/#main-methods) of subscribing. [Look here.](https://jsfiddle.net/sthagman/zjcdsd84/7/) The emit works, but happens before the first render and before `emitNumberActionStream.onValue(..)`, so the emitted number isn't observed. – Sam Sep 10 '15 at 13:29
  • Kefir.emitter is [not supported](https://github.com/rpominov/kefir/issues/88) anymore. – Red Pill May 12 '16 at 09:44