使用 kefirjs 将数据传递给 React 组件

Pass data to React component with kefirjs

我是 ReactJS 的新手 "reactive programming"。我尝试根据this项目创建一个dispatcher、action和store,但我不知道如何将数据传递给组件。

this 示例中它不起作用。

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'));

我认为问题是您使用的是 ES6 语法(这是示例的编写...注意 Readme). You'll need to either use a transpiler like Babel 或将您的 method(param => console.log(param)) 语法转换为普通 JS(即, method(function(param) { console.log(param) });).

在我开始详细回答之前,我想先回答这部分:

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

在示例中,您使用 React 的 props 将作者传递的待办事项链接到主要组件,而不是通过操作。这也是我在示例中采用的方法。

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'));

我修改了你给出的那个不起作用的例子,让它起作用并且更有意义(希望如此)。

Actions 和 Stores 是这样工作的:

操作:

  • 请求发出一个数字

店铺

  • 监听 "EMIT_NUMBER" 动作并发出一个随机数

而实际的组件是这样运行的:

  1. 它通过 props 获取传入组件的前 5 个数字。
  2. 安装后,它开始侦听存储并创建调用动作调度程序的 emitNumber() 动作的 setInterval。间隔是为了显示工作中的反应性,你可以想象有一个按钮可以按下,它会调用 emitNumber()。
  3. 商店观察动作调度程序发出 "EMIT_NUMBER" 并发出一个数字。
  4. 组件观察存储发出的数字并更新组件的状态。
  5. 组件观察到其状态已更改并重新呈现。