Я новичок ie в React Native и изо всех сил пытаюсь получить данные в базу данных Firebase.
По сути, вот поток моих данных:
1. User chooses locations and their trip information ( name, startDate, endDate) --> stored in Redux
2. In the Redux store, at the time user creates the trip, I POST that trip to the Firebase database
3. After that, in the TripsListScreen, I fetch(method: 'GET') the trips from that database to show to the user
Вот Поведение TripsListScreen
просто обновляется снова и снова, хотя я успешно публикую поездки в базу данных. Но ошибка в функции, которая загружает поездки с сервера (так что я думаю, что я не смог успешно извлечь с сервера)
Ошибка видео
Вот TripsListScreen
const TripsListScreen = props => {
const [isLoading, setIsLoading] = useState(false);
const [isRefreshing, setIsRefreshing] = useState(false);
const [error, setError] = useState();
const trips = useSelector(state => state.trips.trips); // The root reducer in App.js is trips
const dispatch = useDispatch();
const loadTrips = useCallback(async() => {
setError(null);
setIsRefreshing(true);
try {
await dispatch(tripActions.fetchTrip());
} catch (error) {
console.log(error)
setError(error);
}
setIsRefreshing(false);
},[dispatch, setIsLoading, setError]);
useEffect(() => {
const willFocus = props.navigation.addListener(
'willFocus',
loadTrips
);
return () => {willFocus.remove();}
},[loadTrips]);
useEffect(() => {
setIsLoading(true);
loadTrips().then(
setIsLoading(false),
);
}, [dispatch, loadTrips])
if(isLoading){
return(
<View>
<ActivityIndicator size='large' color={Colors.primary} />
</View>
)
}
if(!isLoading && trips.length === 0){
return(
<View style={styles.container}>
<Text>No trips created. Let make some!</Text>
</View>
)
}
if (error) {
return (
<View style={[styles.container, {justifyContent: 'center', alignItems: 'center'}]}>
<Text>An error occurred!</Text>
<Button
title="Try again"
onPress={loadTrips}
color={Colors.primary}
/>
</View>
);
}
return(
<Layout style={[styles.container, {justifyContent: 'center', alignItems: 'center'}]}>
<Layout style={styles.header}>
<Layout style={styles.titleContainer}>
<Text style={styles.title}>Let's pack for your trip</Text>
</Layout>
<Layout style={styles.subtitleContainer}>
<Text style={styles.subtitle}>And share it with your friends</Text>
</Layout>
</Layout>
<View style={styles.list}>
<FlatList
onRefresh={loadTrips}
refreshing={isRefreshing}
horizontal={true}
data={trips.reverse()}
keyExtractor={item => item.id}
renderItem={(itemData => {
return(
<TripItem
onSelect={() => props.navigation.navigate('PlanningProcess', {screen: 'MainMapScreen', params: {doNotAddPlace: true}})}
onEdit={() => props.navigation.navigate('PlanningProcess', {screen: 'TripDescription'})}
eventName={itemData.item.name}
startDate={itemData.item.startDate}
endDate={itemData.item.endDate}
/>
)
})}
/>
</View>
</Layout>
);
};
Вот tripReducer
import { ADD_TRIP, SET_TRIP } from '../../actions/trip/trip';
import { Trip } from '../../../src/models/trip';
const initialState = {
trips: []
}
export default tripReducer = (state = initialState, action) => {
switch(action.type){
case ADD_TRIP:
const newTrip = new Trip(
action.tripData.id,
action.tripData.ownerId,
action.tripData.name,
action.tripData.startDate,
action.tripData.endDate,
action.locations
);
return {
...state,
trips: state.trips.concat(newTrip),
}
case SET_TRIP:
return{
trips: action.trips
}
default: return state;
}
}
Вот tripActions
import { Trip } from "../../../src/models/trip";
export const ADD_TRIP = 'ADD_TRIP';
export const SET_TRIP = 'SET_TRIP';
export const addTrip = (name, startDate, endDate, locations) => {
return async (dispatch, getState) => {
const token = getState().auth.user.token;
const userId = getState().auth.user.uid;
const response = await fetch(
`https://...(keep secret for safety)/trips.json?auth=${token}`, {
method: 'POST',
headers:{
'Content-Type': 'application/json'
},
body: JSON.stringify({
name,
startDate,
endDate,
locations,
ownerId: userId,
})
});
const resData = await response.json();
console.log(resData);
dispatch({
type: ADD_TRIP,
tripData:{
id: resData.name,
ownerId: userId,
name,
startDate,
endDate,
locations
}
})
}
};
export const fetchTrip = () => {
return async (dispatch, getState) => {
const userId = getState().auth.user.uid;
try {
const response = await fetch(
'https://...(keep secret for safety)/trips.json'
);
if(!response.ok){
throw new Error('Something went wrong, please try again!')
};
const resData = await response.json();
console.log(resData);
const loadedTrips = [];
for(let key in resData){
loadedTrips.push(new Trip(
key,
resData[key].ownerId,
resData[key].name,
resData[key].startDate,
resData[key].endDate,
resData[key].locations
))
};
dispatch({
type: SET_TRIP,
trips: loadedTrips.filter(trip => trip.ownerId === userId)
})
} catch (error) {
throw error;
}
}
}
Поток хранилища Redux:
1. ADD_TRIP: post trip information to the server (firebase database)
2. SET_TRIP: fetch trip information from the server, which is posted by the ADD_TRIP action ( to display on the screen for the user)
Вот база данных после получения данных от ADD_TRIP
:
Вот правила для базы данных Firebase:
EDIT 1 : я пытался использовать axios
и запрос не выполнен с кодом ошибки 401, что означает, что запрос не был авторизован.
ПОЖАЛУЙСТА, ПОМОГИТЕ