【问题标题】:Pass data to React component with kefirjs使用 kefirjs 将数据传递给 React 组件
【发布时间】:2015-08-25 14:57:31
【问题描述】:

我是 ReactJS 和“反应式编程”的新手。我尝试根据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'));

【问题讨论】:

  • 您能否通过调试器或控制台日志检查数据是否在从操作到 Kefir 或从 Kefir 到组件的过程中丢失?
  • @Moezalez 他们在开菲尔的行动中迷失了方向。 'AppDispatcher' 不发出动作。 jsfiddle.net/69z2wepo/15496

标签: javascript reactjs reactive-programming kefir.js


【解决方案1】:

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

但我不知道如何将数据传递给组件。

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

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. 组件观察到其状态已更改并重新渲染。

【讨论】:

  • 感谢山姆的回答。让我问你一件事。如果你想在getInitialState 函数中发出动作,为什么它不起作用? jsfiddle.net/zjcdsd84/6
  • 发射动作在该示例中有效。您正在尝试使用var number = Actions.emitNumber(); 捕获发出的数字,但.emitNumber() 不返回任何内容,它只是告诉发射器发出一个事件。要捕获您需要订阅的号码emitNumberActionStreamusing any of kefir's ways订阅。 Look here. 发射有效,但发生在第一次渲染之前和 emitNumberActionStream.onValue(..) 之前,因此未观察到发射的数字。
  • Kefir.emitter 不再是not supported
【解决方案2】:

我认为问题在于您使用的是 ES6 语法(这是编写示例的内容......注意Readme)。您需要使用像Babel 这样的转译器,或者将您的method(param =&gt; console.log(param)) 语法转换为普通的JS(即method(function(param) { console.log(param) });)。

【讨论】:

  • 对不起,我没有发布转译版本。请查看我编辑的帖子。
猜你喜欢
  • 2018-07-14
  • 1970-01-01
  • 2022-07-07
  • 2015-01-28
  • 2020-06-01
  • 1970-01-01
  • 2016-10-28
  • 1970-01-01
  • 2021-08-20
相关资源
最近更新 更多