我在redux
和firebase
时遇到了一些问题。是否必须将路由器放到项目的根组件中?
我的一些工作非常适合这个系统,但不是asynchronous
函数,主要是firebase
的函数。
这篇文章基本上是关于firebase.[objects]
的放置方式和位置,以便始终正确阅读。官方文件不是很清楚明确。
我提醒你我是firebase 的新手。
我尝试将它们放在反应循环函数中(例如componentDidMount()
,...),因为渲染后会触发一些,但没有任何操作。
基本上,这就是我所做的:
Service.jsx
function getAll() {
// I had saved some values in the localStorage
const uid = JSON.parse(localStorage.getItem('user')).uid;
// Here the reference to appropriate child in the database
const dbRef = firebase.database().ref().child('events');
// Choosing the user with appropriate's is
const userRef = dbRef.child(uid);
// An array to save fetched values
let answer = [];
// Created a listener
userRef.on('value', snap => {
let rx = snap.val();
for (let item in snap.val()) {
answer.push(rx[ item ]);
}
// Return a promise for the actions
return Promise.resolve({
events: answer
});
});
return Promise.resolve({
events: answer
});
}
Reducer.jsx
export function events(state = { events: [] }, action) {
// --------> Get all
case eventConstants.GET_ALL_REQUEST:
return {
...state,
managingEvent: true,
};
case eventConstants.GET_ALL_SUCCESS:
return {
...state,
events: action.events
};
case eventConstants.GET_ALL_FAILURE:
return state;
default:
return state
}
}
Action.jsx
function getAll() {
return dispatch => {
dispatch(request());
eventService.getAll()
.then(
ans => {
dispatch(success(ans.events));
},
error => {
dispatch(failure(error));
dispatch(alertActions.error(error));
}
);
};
function request() {
return { type: eventConstants.GET_ALL_REQUEST }
}
function success(events) {
return { type: eventConstants.GET_ALL_SUCCESS, events }
}
function failure(error) {
return { type: eventConstants.GET_ALL_FAILURE, error }
}
}
这就是我所做的。现在我正在尝试做:使用store.dispatch(Action.getAll())
检索数据,因为我在搜索组件中使用这些数据。我以这种方式使用它们:
搜索
// usual imports here, connect inculed
import React, { Component } from 'react';
import { connect } from 'react-redux';
class SearchPage extends Component {
// So I first used the constructor
constructor(props){
this.props.dispatch(Action.getAll());
}
componentDidMount() {
// Then here... an same for all others methods of react lifecycle
this.props.dispatch(Action.getAll());
}
render() {
// TODO Don't forget the translation
let { translate, events } = this.props;
....
const table = (
<Table hover>
{tableHeader}
<tbody>
{events.map(item =>
<tr key={item.key}>
<th scope="row">{item.key}</th>
<td>{item.name}</td>
<td>{item.startDate}</td>
<td>{item.endDate}</td>
</tr>
)}
</tbody>
</Table>
);
...
}
const mapStateToProps = (state) => {
const { events } = state.events;
const translate = getTranslate(state.locale);
return {
events,
translate,
};
}
const connectedPage = connect(mapStateToProps)(SearchPage);
export { connectedPage as SearchPage };
有时它会被罚款,然后当我在线更新数据库然后重新渲染时,它说event
为空或未定义,我可以理解,因为Reducer.js
的过渡。
But what should I do now ?
现在是我的问题。
感谢您阅读本文,感谢您的帮助。
:)
答案 0 :(得分:2)
这里的问题是服务中的getAll
函数不会等待监听器完成。因此,答案变量将始终为[]
。
解决方案是返回new promise instance
,只有在从firebase接收数据后才能解析。
更新了Service.jsx
function getAll () {
// I had saved some values in the localStorage
const uid = JSON.parse(localStorage.getItem('user')).uid;
// Here the reference to appropriate child in the database
const dbRef = firebase.database().ref().child('events');
// Choosing the user with appropriate's is
const userRef = dbRef.child(uid);
// An array to save fetched values
const answer = [];
return new Promise((resolve) => {
// Created a listener
userRef.on('value', (snap) => {
const rx = snap.val();
for (const item in snap.val()) {
answer.push(rx[item]);
}
// Return a promise for the actions
resolve({
events: answer
});
});
});
}
答案 1 :(得分:1)
我相信,如果事件的提取尚未完成,则在Services.jsx上的getAll()(return Promise...
之外)结束时的userRef.on('value'...
会导致函数getAll返回undefined。我会像这样重构Service.jsx(Firebase方法已经返回promise,所以你可以直接返回它们):
function getAll() {
const uid = JSON.parse(localStorage.getItem('user')).uid;
const dbRef = firebase.database().ref().child('events');
const userRef = dbRef.child(uid);
let answer = [];
return userRef.on('value', snap => {
snapshot.forEach((snap) => answer.push(snap.val()));
return {
events: answer
};
});
}
您可以尝试的另一种方法是创建一个不呈现任何内容的特殊组件,仅负责在componentDidMount上附加firebase侦听器并在componentWillUnmount上删除它(类似下面的代码),然后将这个特殊组件导入到你的SearchPage.jsx。
class FirebaseListenToEvents extends Component {
componentDidMount() {
const uid = JSON.parse(localStorage.getItem('user')).uid;
const dbRef = firebase.database().ref().child('events');
this.userRef = dbRef.child(uid);
this.userRef.on('value', (snap) => {
this.props.onUpdateEvent(snap.key, snap.val());
});
}
componentWillUnmount() {
this.userRef.off('value');
}
render() {
return null;
}
}
我不确定哪种方法最适合您,但我希望这能为您提供一些有关如何处理Firebase&amp; amp;反应。这article似乎也比我更好地解释了它。如果您有问题,请在评论中问我。祝你好运!