等待 onSnapshot 获取数据
wait for onSnapshot fetching data
我目前正在学习 React Native (Expo)。
我想使用 redux 和 react-native-firebase。
当我在我的应用程序启动时订阅 firebase (onSnapshot) 时,它 returns 来自 firebase 的数据。但由于 onSnapchot 没有 return 承诺,我不能将它用于我的应用程序加载组件。
因此,我还需要从firebase中获取数据以防止应用程序闪烁。
结果是在我的应用程序启动时我获取了两次数据。
所以我的问题是:
我如何等待 onSnapshot 从 firebase 加载我的数据?
谢谢
const Manager = (props) => {
//STATE
const [init, setInit] = useState(false);
//HOOKS
const fetchData = useFetchData();
useInitFirebaseSubscriptions();
//FUNCTIONS
async function onInit() {
console.log('[MANAGER]: loading app...');
await Promise.all([fetchData()]);
}
function onFinishedInit() {
console.log('[MANAGER]: ...app loading successfull!');
setInit(true);
}
//RETURN
if (!init) {
return <AppLoading startAsync={onInit} onFinish={onFinishedInit} onError={console.warn} />;
} else {
return props.children;
}
};
export default Manager;
//INITIAL FETCH BEFORE RENDERING
export function useFetchData() {
const dispatch = useDispatch();
return async function () {
try {
await firestore()
.collection('users')
.get()
.then((querySnapshot) => dispatch(actions.fetch(querySnapshot)));
} catch (err) {
console.log(err.message);
}
};
}
//INIT SUBSCRIPTIONS TO FIREBASE
export function useInitFirebaseSubscriptions() {
const dispatch = useDispatch();
useEffect(() => {
console.log('[CONTROLLER]: subscribed to Firebase');
const unsubscribe = firestore()
.collection('users')
.onSnapshot(
(querySnapshot) => dispatch(action.fetch(querySnapshot)),
(error) => console.log(error)
);
return () => {
unsubscribe();
console.log('[CONTROLLER]: unsubscribed from Firebase');
};
}, []);
}
[MANAGER]: loading app...
[MANAGER]: subscribed to Firebase
[USER_REDUCER]: fetched data
[USER_REDUCER]: fetched data
[MANAGER]: ...app loading successfull!
我认为您可以通过在 redux 中添加一些“正在加载”状态来实现您的目标,以便在您主动从 firebase 获取数据时使用。添加特定于此数据的状态和减速器案例 fetching/loading。
示例代码:
export function useInitFirebaseSubscriptions() {
const dispatch = useDispatch();
useEffect(() => {
console.log('[CONTROLLER]: subscribed to Firebase');
dispatch(action.startFetch()); // <-- dispatch starting data fetch
const unsubscribe = firestore()
.collection('users')
.onSnapshot(
(querySnapshot) => {
dispatch(action.fetch(querySnapshot));
dispatch(action.completedFetch()); // <-- done fetching
},
(error) => {
console.log(error);
dispatch(action.completedFetch()); // <-- done fetching
},
);
return () => {
unsubscribe();
console.log('[CONTROLLER]: unsubscribed from Firebase');
};
}, []);
};
Select 来自 redux 存储的加载状态并有条件地渲染加载 UI,否则渲染传递的子项。
const Manager = (props) => {
const isFetchingData = useSelector(state => state.isFetchingData);
if (isFetchingData) {
return <AppLoadingIndicator />;
}
return props.children; // *
};
* 通常,您可以在此处使用一些额外的条件渲染,具体取决于数据是否实际上 fetched/returned 并且只是空的,或者是否存在错误等。 .. 基本上提供了一些结果状态。
我目前正在学习 React Native (Expo)。 我想使用 redux 和 react-native-firebase。
当我在我的应用程序启动时订阅 firebase (onSnapshot) 时,它 returns 来自 firebase 的数据。但由于 onSnapchot 没有 return 承诺,我不能将它用于我的应用程序加载组件。 因此,我还需要从firebase中获取数据以防止应用程序闪烁。
结果是在我的应用程序启动时我获取了两次数据。
所以我的问题是: 我如何等待 onSnapshot 从 firebase 加载我的数据?
谢谢
const Manager = (props) => {
//STATE
const [init, setInit] = useState(false);
//HOOKS
const fetchData = useFetchData();
useInitFirebaseSubscriptions();
//FUNCTIONS
async function onInit() {
console.log('[MANAGER]: loading app...');
await Promise.all([fetchData()]);
}
function onFinishedInit() {
console.log('[MANAGER]: ...app loading successfull!');
setInit(true);
}
//RETURN
if (!init) {
return <AppLoading startAsync={onInit} onFinish={onFinishedInit} onError={console.warn} />;
} else {
return props.children;
}
};
export default Manager;
//INITIAL FETCH BEFORE RENDERING
export function useFetchData() {
const dispatch = useDispatch();
return async function () {
try {
await firestore()
.collection('users')
.get()
.then((querySnapshot) => dispatch(actions.fetch(querySnapshot)));
} catch (err) {
console.log(err.message);
}
};
}
//INIT SUBSCRIPTIONS TO FIREBASE
export function useInitFirebaseSubscriptions() {
const dispatch = useDispatch();
useEffect(() => {
console.log('[CONTROLLER]: subscribed to Firebase');
const unsubscribe = firestore()
.collection('users')
.onSnapshot(
(querySnapshot) => dispatch(action.fetch(querySnapshot)),
(error) => console.log(error)
);
return () => {
unsubscribe();
console.log('[CONTROLLER]: unsubscribed from Firebase');
};
}, []);
}
[MANAGER]: loading app...
[MANAGER]: subscribed to Firebase
[USER_REDUCER]: fetched data
[USER_REDUCER]: fetched data
[MANAGER]: ...app loading successfull!
我认为您可以通过在 redux 中添加一些“正在加载”状态来实现您的目标,以便在您主动从 firebase 获取数据时使用。添加特定于此数据的状态和减速器案例 fetching/loading。
示例代码:
export function useInitFirebaseSubscriptions() {
const dispatch = useDispatch();
useEffect(() => {
console.log('[CONTROLLER]: subscribed to Firebase');
dispatch(action.startFetch()); // <-- dispatch starting data fetch
const unsubscribe = firestore()
.collection('users')
.onSnapshot(
(querySnapshot) => {
dispatch(action.fetch(querySnapshot));
dispatch(action.completedFetch()); // <-- done fetching
},
(error) => {
console.log(error);
dispatch(action.completedFetch()); // <-- done fetching
},
);
return () => {
unsubscribe();
console.log('[CONTROLLER]: unsubscribed from Firebase');
};
}, []);
};
Select 来自 redux 存储的加载状态并有条件地渲染加载 UI,否则渲染传递的子项。
const Manager = (props) => {
const isFetchingData = useSelector(state => state.isFetchingData);
if (isFetchingData) {
return <AppLoadingIndicator />;
}
return props.children; // *
};
* 通常,您可以在此处使用一些额外的条件渲染,具体取决于数据是否实际上 fetched/returned 并且只是空的,或者是否存在错误等。 .. 基本上提供了一些结果状态。