我对React很陌生,我正试图围绕着Reflux。
这是我的情景:
我目前有一个非常简单的应用程序,它从休息api调用一些歌曲数据,一旦被检索,它就存储在state.songs中(这发生在歌曲存储区的Init函数中):
var SongStore = Reflux.createStore({
listenables: [SongActions],
getInitialState: function() {
return []
},
init: function() {
request('http://127.0.0.1:1337/api/songs', function(error, response, body) {
if (!error && response.statusCode == 200) {
var content = JSON.parse(body);
this.trigger(content);
}
}.bind(this));
},
onHandleClick: function(album_link) {
// this.state.songs is undefined here??
}
});
以下是呈现歌曲数据的组件:
var Home = React.createClass({
mixins: [Reflux.connect(SongStore, 'songs')],
render: function() {
return (
<div className={'react-app-home'}>
<div className="float-left">
<div className="song-data">
{this.state.songs.map(function(song) {
return <div><p>{song.lyrics}</p></div>
})}
</div>
</div>
<div className="float-right">
<AlbumList />
</div>
</div>
);
}
});
这一切都按预期工作。
我还有一个专辑列表,这些专辑在其自己的组件中呈现(并拥有它自己的商店),我试图在专辑中连接点击功能item,所以一旦点击了一个专辑标题,就会过滤this.state.songs并重新渲染歌曲组件。
我遇到的问题是当我尝试从歌曲商店访问this.state.songs时,它是未定义的(请参阅上面歌曲商店中的onHandleClick func)。
专辑列表组件:
var AlbumList = React.createClass({
mixins: [Reflux.connect(AlbumStore, 'albums'),
Reflux.connect(SongStore, 'songs')],
render: function() {
return (
<div className="album-list">
{this.state.albums.map(function(album) {
return <p onClick={SongStore.onHandleClick.bind(null, album.album_link)}>{album.album_name}</p>
})}
</div>
);
}
});
专辑列表商店:
var AlbumStore = Reflux.createStore({
listenables: [AlbumActions],
getInitialState: function() {
return [];
},
onReload: function() {
request('http://0.0.0.0:1337/api/albums', function(error, response, body) {
if (!error && response.statusCode == 200) {
var content = JSON.parse(body);
this.trigger(content);
}
}.bind(this));
},
init: function() {
this.onReload();
}
});
任何人都可以帮助我吗?一些解释的答案很棒,所以我可以理解问题是什么。
谢谢!
答案 0 :(得分:0)
您应该使用handleClick或从组件到商店的任何其他调用的操作。我还建议将你的api电话与商店分开。以下是https://github.com/calitek/ReactPatterns React.14 / ReFluxSuperAgent。
中的示例app.js
'use strict';
import React from 'react';
import ReactDom from 'react-dom';
import AppCtrl from './components/app.ctrl.js';
import Actions from './actions/api.Actions';
import ApiStore from './stores/Api.Store';
window.ReactDom = ReactDom;
Actions.apiInit();
ReactDom.render( <AppCtrl />, document.getElementById('react') );
请注意操作和api.store导入。 这是api.store。
import Reflux from 'reflux';
import Actions from '../actions/api.Actions';
import ApiFct from '../utils/sa.api';
let ApiStoreObject = {
newData: {
"React version": "0.14",
"Project": "ReFluxSuperAgent",
"currentDateTime": new Date().toLocaleString()
},
listenables: Actions,
apiInit() { ApiFct.setData(this.newData); },
apiInitDone() { ApiFct.getData(); },
apiSetData(data) { ApiFct.setData(data); }
}
const ApiStore = Reflux.createStore(ApiStoreObject);
export default ApiStore;
apiInit在这里做一个setData但它可能是初始的get调用。 这就是api。
import request from 'superagent';
import apiActions from '../actions/api.Actions';
import saActions from '../actions/sa.Actions';
module.exports = {
getData() { request.get('/routes/getData').end((err, res) => { this.gotData(res.body); }); },
gotData(data) { saActions.gotData1(data); saActions.gotData2(data); saActions.gotData3(data); },
setData(data) { request.post('/routes/setData').send(data).end((err, res) => { apiActions.apiInitDone(); }) },
};
这里我们使用动作将数据传递给商店。 这是商店。
import Reflux from 'reflux';
import Actions from '../actions/sa.Actions';
import AddonStore from './Addon.Store';
import MixinStoreObject from './Mixin.Store';
function _GotData(data) { this.data1 = data; BasicStore.trigger('data1'); }
let BasicStoreObject = {
init() { this.listenTo(AddonStore, this.onAddonTrigger); },
data1: {},
listenables: Actions,
mixins: [MixinStoreObject],
onGotData1: _GotData,
onAddonTrigger() { BasicStore.trigger('data2'); },
getData1() { return this.data1; },
getData2() { return AddonStore.data2; },
getData3() { return this.data3; }
}
const BasicStore = Reflux.createStore(BasicStoreObject);
export default BasicStore;
请注意,回流允许您在触发器中传递参数。 这是组件。
import React from 'react';
import BasicStore from '../stores/Basic.Store';
let AppCtrlSty = {
height: '100%',
padding: '0 10px 0 0'
}
const getState = () => {
return {
Data1: BasicStore.getData1(),
Data2: BasicStore.getData2(),
Data3: BasicStore.getData3()
};
};
class AppCtrlRender extends React.Component {
render() {
let data1 = JSON.stringify(this.state.Data1, null, 2);
let data2 = JSON.stringify(this.state.Data2, null, 2);
let data3 = JSON.stringify(this.state.Data3, null, 2);
return (
<div id='AppCtrlSty' style={AppCtrlSty}>
React 0.14 ReFlux with SuperAgent<br/><br/>
Data1: {data1}<br/><br/>
Data2: {data2}<br/><br/>
Data3: {data3}<br/><br/>
</div>
);
}
}
export default class AppCtrl extends AppCtrlRender {
constructor() {
super();
this.state = getState();
}
componentDidMount = () => { this.unsubscribe = BasicStore.listen(this.storeDidChange); }
componentWillUnmount = () => { this.unsubscribe(); }
storeDidChange = (id) => {
switch (id) {
case 'data1': this.setState({Data1: BasicStore.getData1()}); break;
case 'data2': this.setState({Data2: BasicStore.getData2()}); break;
case 'data3': this.setState({Data3: BasicStore.getData3()}); break;
default: this.setState(getState());
}
}
}
我们没有使用mixins。 React类正在弃用mixins,所以现在是不用的好时机。使用额外的商店和api util可能看起来有点过分,但好的做法总是很好的做法。
Map允许使用可选的参数map(function(item){},this)传递它;