ReactJS Flux:检测组件之间的存储数据变化(不是父子关系)

时间:2016-03-30 12:29:00

标签: reactjs reactjs-flux

我有两个组成部分;菜单和信息。我需要在两个组件之间共享数据。我正在使用Facebook Flux模式。商店类由EventEmitter进行更改检测。检测在父母与子女的关系中起作用。

enter image description here

蓝色是菜单。红色是信息组件。我的网站之前没有使用过ReactJS。我正在尝试将ReactJS用于网站的一部分。我想在整个应用程序中使用ReactJS是一种可能的解决方案,react-route .. ?,但是我不能在这个时候这样做。

有人知道吗?

================================

编辑1

我将整个代码发布到了这个要点。

https://gist.github.com/y-zono/e1abf9e85a4707d81286b49f6a7f0117

我的目标是菜单和信息计数器显示相同的值。现在只增加了菜单计数器。

enter image description here

=============================================== =

Edit2 Solved

var React = require('react');
var ReactDOM = require('react-dom');
var Menu = require('./components/Menu.react');
var Info = require('./components/Info.react');
var CommonStore = require('./stores/CommonStore');

function renderMenu() {
    var state = CommonStore.getState();
    ReactDOM.render(
        <Menu data={state} />,
        document.getElementById('menu')
    );
}

CommonStore.addChangeListener(renderMenu);
renderMenu();

function renderInfo() {
    var state = CommonStore.getState();
    ReactDOM.render(
        <Info data={state} />,
        document.getElementById('info')
    );
}

CommonStore.addChangeListener(renderInfo);
renderInfo();

2 个答案:

答案 0 :(得分:1)

我认为主要问题是您没有使用商店来设置组件中的状态。

Info.react.js应为:

var React = require('react');
var CommonStore = require('../stores/CommonStore');
var CommonActionCreators = require('../actions/CommonActionCreators');

var Info = React.createClass({
    componentDidMount: function() {
        CommonStore.addChangeListener(this._handleChangeStore);
    },
    componentWillUnmount: function() {
        CommonStore.remChangeListener(this._handleChangeStore);
    },
    getInitialState() {
        return {
            clickFlag: CommonStore.getClickFlag()
        };
    },
    _handleChangeStore: function() {
        this.setState(clickFlag: CommonStore.getClickFlag();
        if (this.state.clickFlag) {
            console.log("menu is clicked"); // I want to detect the change.
        }
    },
});

此外,您还需要一个重置clickFlag的条件。

更新:

查看代码时,不应让每个组件使用自己独立的<script>。相反,你应该有一个中央js(通常称为app.js),然后显示菜单和信息组件。然后,您不需要将菜单分成js / menu.js和js / components / Menu.react.js。同样,您不应将info组件分为js / info.js和js / components / Menu.react.js。你应该只有js / components / Menu.react.js和js / components / Info.react.js,app.js处理你现在拥有的js / menu.js和js / info.js。

示例:

的index.html

<div>
  <div id="app"></div>
</div>

<script src="js/app.js"></script>

app.js

var React = require('react');
var ReactDOM = require('react-dom');
var Menu = require('./components/Menu.react');
var Info = require('./components/Info.react');

function renderDOM() {
    ReactDOM.render(
        <App />,
        document.getElementById('app')
    );
}

renderDOM();

Info.react.js

var Info = React.createClass({
    componentDidMount: function() {
        CommonStore.addChangeListener(this._handleChangeStore);
    },
    componentWillUnmount: function() {
        CommonStore.remChangeListener(this._handleChangeStore);
    },
    getInitialState() {
        return {
            count: CommonStore.getState()
        };
    },
    _handleChangeStore: function() {
        this.setState(count: CommonStore.getState();
    },
    render: function() {
        return (
            <div>
                info: {this.state.count}
            </div>
        );
    },
});

答案 1 :(得分:1)

不是订阅组件级别的商店,为什么不订阅呈现组件的位置(例如menu.js)?

您可以将渲染代码包装在一个函数中,并在该函数中读取存储的状态,然后将其作为prop传递给组件。您可以手动调用render()来进行第一次渲染,也可以订阅将渲染函数作为回调传递的商店:

// menu.js
var React = require('react');
var ReactDOM = require('react-dom');
var Menu = require('./components/Menu.react');
var CommonStore = require('../stores/CommonStore');

function render() {
  var state = CommonStore.getState();
  ReactDOM.render(
      <Menu data={state} />,
      document.getElementById('menu')
  );
}

CommonStore.addChangeListener(render);
render();

注意:我不确定您的商店有什么吸引力,所以我刚刚编写了一些示例代码。

您的组件代码就是:

// ./components/Menu.react.js
var React = require('react');
var CommonActionCreators = require('../actions/CommonActionCreators');

var Menu = React.createClass({
    _handleClickMenu: function() {
        CommonActionCreators.setMenuClieckOn();
    }
});

然后重复Info组件的过程。

这个小提琴展示了这种方法在实践中的一个例子(有一些虚拟组件,存储和动作创建者),以证明这个概念有效:https://jsfiddle.net/vgskht45/1/