ReactJS Flux:检测组件之间的存储数据变化(不是父子关系)
ReactJS Flux: detect store data change between components (not parent and child relationship)
我有两个组件;菜单和信息。我需要在两个组件之间共享数据。我正在使用 Facebook Flux 模式。商店 class 通过 EventEmitter 进行了更改检测。检测父子关系。
蓝色的是菜单。红色是信息组件。我的网站之前没有使用 ReactJS。我正在尝试将 ReactJS 用于网站的一部分。我想对整个应用程序使用 ReactJS 是一种可能的解决方案,react-route..?,但我现在不能这样做。
有人知道吗?
==================================
编辑 1
我将我的整个代码发布到这个要点。
https://gist.github.com/y-zono/e1abf9e85a4707d81286b49f6a7f0117
我的目标是菜单和信息计数器显示相同的值。现在只增加了菜单计数器。
============================================= ===
Edit2 已解决
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();
我认为主要问题是您没有使用商店来设置组件中的状态。
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。同样,您不应该将信息组件分成 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>
);
},
});
与其在组件级别订阅商店,为什么不在呈现组件的位置订阅(例如 menu.js)?
您可以将渲染代码包装在一个函数中,并在该函数中读取商店的状态,然后再将其作为道具传递给您的组件。您可以手动调用 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
组件重复该过程。
此 fiddle 展示了此方法在实践中的一个示例(使用一些虚拟组件、存储和动作创建器),以证明该概念有效:https://jsfiddle.net/vgskht45/1/
我有两个组件;菜单和信息。我需要在两个组件之间共享数据。我正在使用 Facebook Flux 模式。商店 class 通过 EventEmitter 进行了更改检测。检测父子关系。
蓝色的是菜单。红色是信息组件。我的网站之前没有使用 ReactJS。我正在尝试将 ReactJS 用于网站的一部分。我想对整个应用程序使用 ReactJS 是一种可能的解决方案,react-route..?,但我现在不能这样做。
有人知道吗?
==================================
编辑 1
我将我的整个代码发布到这个要点。
https://gist.github.com/y-zono/e1abf9e85a4707d81286b49f6a7f0117
我的目标是菜单和信息计数器显示相同的值。现在只增加了菜单计数器。
============================================= ===
Edit2 已解决
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();
我认为主要问题是您没有使用商店来设置组件中的状态。
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。同样,您不应该将信息组件分成 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>
);
},
});
与其在组件级别订阅商店,为什么不在呈现组件的位置订阅(例如 menu.js)?
您可以将渲染代码包装在一个函数中,并在该函数中读取商店的状态,然后再将其作为道具传递给您的组件。您可以手动调用 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
组件重复该过程。
此 fiddle 展示了此方法在实践中的一个示例(使用一些虚拟组件、存储和动作创建器),以证明该概念有效:https://jsfiddle.net/vgskht45/1/