将firestore onSnapShot与react redux一起使用的正确方法
Posted
技术标签:
【中文标题】将firestore onSnapShot与react redux一起使用的正确方法【英文标题】:correct way to use firestore onSnapShot with react redux 【发布时间】:2018-09-18 21:03:51 【问题描述】:我正在尝试找出将 firestore.onSnapshot 与 react-redux 一起使用的正确方法。
我目前在我的操作文件中有此代码,我在我的组件中调用 componentWillMount()
。
export const fetchCheckins = () => async (dispatch) =>
const currentUser = firebaseService.auth();
try
let timestamp = (new Date());
//set timestamp for beginning of today
timestamp.setHours(0);
//get checkins today
let checkinstoday = (await firebaseService.firestore().collection(`/checkins/$currentUser.uid/log`).where("timestamp",">=",timestamp).orderBy("timestamp","desc").get()).docs.map(doc => doc.data());
//set timestamp for beggining of week
timestamp.setDate(-(timestamp.getDay()));
//get checkins (week)
let checkinsweek = (await firebaseService.firestore().collection(`/checkins/$currentUser.uid/log`).where("timestamp",">=",timestamp).orderBy("timestamp","desc").get()).docs.map(doc => doc.data());
//set timestamp for begging of month
timestamp.setDate(0);
//get checkins (month)
let checkinsmonth = (await firebaseService.firestore().collection(`/checkins/$currentUser.uid/log`).where("timestamp",">=",timestamp).orderBy("timestamp","desc").get()).docs.map(doc => doc.data());
dispatch(type: FETCH_CHECKINS, payload: today: checkinstoday, week: checkinsweek, month: checkinsmonth);
catch(e)
console.error(e);
;
这工作正常,正确的数据被发送到组件并显示。问题是,如果用户签入,签入数据应该调整,但它不会,因为我只获取一次数据并发送它,并且状态不会重新渲染。
我的问题是我应该如何处理这个问题?我是否使用.onSnapshot()
而不是.get()
?我是否从.checkin()
动作创建者那里调用.fetchCheckins()
?我如何根据最佳实践进行处理?谢谢
【问题讨论】:
【参考方案1】:根据 firestore 的文档,如果您需要实时更新,您应该使用 onSnapshot: https://firebase.google.com/docs/firestore/query-data/listen
在您的情况下,如果您使用 .get() - 您将获得一次更新,如果有任何数据更改,firestore 将不会通知您。这就是您没有看到变化的原因。
附:结帐 redux-firestore:https://github.com/prescottprue/redux-firestore - 这是一个很好的库,可以帮助您进行 redux 绑定。
【讨论】:
有没有关于如何使用redux-firestore的好例子,我的状态对象中出现了firestore,但我不确定如何获取集合【参考方案2】:您可以像这样订阅您的列表:
function subscribeToExperiences()
return eventChannel((emmiter: any) =>
experiencesRef.onSnapshot( includeMetadataChanges: true , snapshot =>
const experiences: IExperience[] = snapshot.docChanges().map(change => (
id: change.doc.id,
title: change.doc.data().title
));
if (snapshot.docChanges().length !== 0)
emmiter(experiences);
);
return () => experiencesRef;
);
function* fetchExperiences(_: ExperiencesFetchRequested)
const channel = yield call(subscribeToExperiences);
try
while (true)
const experiences = yield take(channel);
yield put(new ExperiencesFetchSucceeded(experiences));
finally
if (yield cancelled())
channel.close();
subscribeToExperiences
使用 redux-saga
eventChannel
。 eventChannel
接收到一个 emmiter,该 emmiter 会生成一个 saga 效果以与 take
一起使用。 eventChannel
必须返回一个函数来关闭连接,但是 afaik .onSnapshot
连接不需要显式关闭,这就是我返回一个虚拟函数的原因。
【讨论】:
您确定不需要关闭连接吗? @FrankvanPuffelen 表示他们 need to be以上是关于将firestore onSnapShot与react redux一起使用的正确方法的主要内容,如果未能解决你的问题,请参考以下文章
React:如何通过 Firestore onSnapshot 和 useEffect 使用最新状态?
Firestore onSnapshot 通过 onEffect 中的状态附加到数组
Firestore 抛出“onSnapshot() 需要 1 到 4 个参数”