Can't test Apollo GraphQL query's loading state - react-native

guys. I have a query that gets data from backend, while query didn't get data I'm showing '...Loading' text. Now I want to test it, but I can't. Test's logic is: if loading state is true, check if we have '...Loading' text.
Here is my query:
const [getCards, { data: cardsData, error: cardsError, loading: cardsLoading }] = useLazyQuery(
GET_LIST,
{
fetchPolicy: 'no-cache',
}
);
Here is my check of loading state:
if (cardsLoading) {
return (
<View
style={{
width: '100%',
height: '100%',
backgroundColor: 'white',
alignItems: 'center',
justifyContent: 'center',
}}
>
<Text>...Loading</Text>
</View>
);
}
And finally here is my test:
const getCardsMock = [
{
request: {
query: GET_LIST,
},
result: {
cards: {
id: 0,
name: 'card',
},
}
},
];
it('Loading state test', async () => {
const component = renderer.create(
<MockedProvider mocks={getCardsMock} addTypename={false}>
<HomeViewApollo />
</MockedProvider>
);
const tree = component.toJSON();
expect(tree.children).toContain('...Loading');
});
After running test I got an error telling me that expected value isn't equal to received value. Received value is array with component, that I render, if loading is done.
I'm not sure but looks like that component's loading state never changes during the test. Do you have an idea how to fix it?

I rewrote test like that
it('Loading state test', async () => {
let wrapper = render(
<MockedProvider mocks={[getCardsMock]} addTypename={false}>
<HomeViewApollo />
</MockedProvider>
);
await waitFor(() => [
expect(wrapper.queryByTestId('loadingIndicator')).toBeTruthy()
]);
});
Now it works.

Related

INVALID_STATE_ERR (React native)

What i am trying to do is simple. But not having enough knowledge about react state caused the problem. In my tab i took typing useState as false. I am trying to get the state when user is typing. By connecting websocket when user is typing i am sending type: "is_typing" data. And when receive is_typing i am trying to change the typing state to true and set timeout 500ms so that it won't show typing if it doesn't get onkeypress.
const Sock = () => {
const [typing, setTyping] = useState(false)
const url = endpoint + "chat/" + "thorOdin" + "/" + "?token=" + token
const ws = new WebSocket(url)
useEffect(() => {
if (token) {
ws.onopen = function () {
console.log("Chat Websoket Connected");
};
ws.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.command === "is_typing") {
setTyping(true)
setTimeout(() => {
setTyping(false)
}, 500);
}
};
ws.onerror = (e) => {
// an error occurred
console.log(e.message);
};
ws.onclose = function () {
console.log("WebSocket Client disconnected");
};
}
}, []);
function typingHandle(e){
ws.send(
JSON.stringify({
command: "is_typing",
text: `is typing ...`,
user: "me",
})
);
}
return (
<View>
{typing==true?
<Text style={{marginTop:50}}>Typing</Text>:
<View></View>
}
<TextInput placeholderTextColor={'gray'} style={{
color: 'white',
backgroundColor: '#262626',
borderRadius: 20,
paddingLeft: 10,
height: 40,
width: '80%',
marginLeft: 10,
marginTop:100
}} placeholder='Write Message..'
onKeyPress={typingHandle}/>
</View>
)
}
It's working. But after 4-5 sec it showing Uncaught error "INVALID_STATE_ERR". Can anyone tell what am i doing wrong here???
I am trying to get typing state of user through socket connection.

React Native: How to test a async component snapshot with Jest/Testing-library?

I am trying to create a test for an async component in React Native. This component uses useEffect to fetch for data, sets it to a state variable and loads the screen accordingly. Once it is all loaded I'd like to compare it to a snapshot. The issue I am having is my test is synchronous, when I check the rendered snapshot it has my loading indicator.
How can I wait for it to load the data and then perform tests?
All the examples and tutorials I find are for sync components, involving simple tasks like checking a button for a specific title, this and the other. I've tried waitFor function but it times out before the data is fetched, apparently it has a 5 second limit. Or maybe I should mock a fetch (?) but my component doesn't take any props to inject the data into it.
To be honest I am very confused on how to approach this. I've never done any automated tests before.
After much confusion in my head I figured it out.
In Jest, whenever you use an external source like an API call using fetch or axios, you have to mock it. This means that Jest will take any axios requests from your component or function and instead of calling the real axios it will call your mock axios automatically. This was the explanation that I was missing and the source of my confusion. The beauty of jest mocking is that you will always get the same data for your tests keeping results and assertions consistent.
There are many ways to mock Axios with Jest including libraries for this specific purpose like jest-mock-axios and MSW (Mock Service Worker) but I couldn't get them to work in my case.
I found a much easier way without the need of external libraries described in the following YouTube tutorial. This guy knows how to explain things and he has a newer video using MSW (link in the YouTube comments).
YouTube: Mocking Axios in Jest + Testing Async Functions
Solution
This is the component to be tested, as you can see there is a axios request triggered by useEffect on mount.
/screens/Home.tsx
import React, { useState, useEffect, memo } from "react";
import { FlatList, StyleSheet } from "react-native";
import { Button } from "react-native-elements";
import axios from "axios";
import Item from "../components/Item";
import AppConfig from "../AppConfig.json";
import { View, Text, ActivityIndicator } from "../components/Themed";
import Toast from "react-native-toast-message";
import { RootTabScreenProps } from "../types";
let _isMounted = false;
function Home({ navigation }: RootTabScreenProps<"Shop">) {
const [items, setItems] = useState([]);
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [error, setError] = useState("");
useEffect(() => {
_isMounted = true;
loadData();
return () => {
_isMounted = false;
};
}, []);
async function loadData(cb?: any) {
try {
axios.get(`${AppConfig.api}/products`).then((res) => {
if (!_isMounted) return;
if (res.status === 200) {
const { data } = res;
setItems(data);
} else {
setError(`Error ${res.status}: failed to load products`);
}
setLoading(false);
setRefreshing(false);
if (typeof cb === "function") cb();
});
} catch (error) {
setLoading(false);
setRefreshing(false);
setError("Failed to load products");
// console.log(error);
}
}
if (loading && !error) {
return (
<View style={styles.containerCenter}>
<ActivityIndicator size={"large"} color="primary" />
</View>
);
} else if (!loading && error) {
return (
<View style={styles.containerCenter}>
<Text>{error}</Text>
<Button
title="Try again"
onPress={() => {
setLoading(true);
setError("");
loadData();
}}
/>
</View>
);
} else {
return (
<View style={styles.container}>
<FlatList
columnWrapperStyle={{ justifyContent: "space-between" }}
data={items}
numColumns={2}
renderItem={({ item }: any) => {
return (
<Item
item={item}
onPress={() => navigation.push("Product", item)}
/>
);
}}
keyExtractor={(item: object, index: any) => index}
refreshing={refreshing}
onRefresh={() => {
setRefreshing(true);
loadData(() => {
Toast.show({
type: "success",
text1: "Product list refreshed",
position: "bottom",
});
});
}}
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
},
containerCenter: {
flex: 1,
justifyContent: "center",
alignItems: "center",
},
title: {
fontSize: 20,
fontWeight: "bold",
},
separator: {
marginVertical: 30,
height: 1,
width: "80%",
},
textError: {
fontSize: 18,
marginBottom: 10,
maxWidth: 250,
},
});
export default memo(Home);
Step 1
Create a folder at the root of your project called __mocks__ (or wherever your source code is!) and create a file called axios.js containing the following object:
/__mocks__/axios.js
export default {
get: jest.fn(() =>
Promise.resolve({
headers: {},
config: {},
status: 200,
statusText: "OK",
data: [
{
id: 1,
title: "Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptops",
price: 109.95,
description:
"Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday",
category: "men's clothing",
image: "https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg",
rating: { rate: 3.9, count: 120 },
},
{
id: 2,
title: "Mens Casual Premium Slim Fit T-Shirts ",
price: 22.3,
description:
"Slim-fitting style, contrast raglan long sleeve, three-button henley placket, light weight & soft fabric for breathable and comfortable wearing. And Solid stitched shirts with round neck made for durability and a great fit for casual fashion wear and diehard baseball fans. The Henley style round neckline includes a three-button placket.",
category: "men's clothing",
image:
"https://fakestoreapi.com/img/71-3HjGNDUL._AC_SY879._SX._UX._SY._UY_.jpg",
rating: { rate: 4.1, count: 259 },
},
{
id: 3,
title: "Mens Cotton Jacket",
price: 55.99,
description:
"great outerwear jackets for Spring/Autumn/Winter, suitable for many occasions, such as working, hiking, camping, mountain/rock climbing, cycling, traveling or other outdoors. Good gift choice for you or your family member. A warm hearted love to Father, husband or son in this thanksgiving or Christmas Day.",
category: "men's clothing",
image: "https://fakestoreapi.com/img/71li-ujtlUL._AC_UX679_.jpg",
rating: { rate: 4.7, count: 500 },
},
],
})
),
};
Adjust the response from your Promise.resolve(...) to whatever you expect your real API to return. Also, make sure you are mocking the function by using jest.fn() otherwise this will not work.
You can also add different properties to you mocked axios object like post, update, put or whatever type of request you need to mock.
Step 2
In the root of your source code again, create a folder called __tests__ and inside of it create a folder called screens. Then create your test file, to keep things consistent I named mine Home.test.js.
/__tests__/screens/Home.test.js
import renderer from "react-test-renderer";
import axios from "axios";
import { act } from "#testing-library/react-native";
import Home from "../../screens/Home";
// Important:
// By calling this, jest will know not to use the real axios and will load it
// from your __mocks__ folder.
jest.mock("axios");
describe("<Home />", () => {
let wrapper;
it("renders items", async () => {
await act(async () => {
// This is where the magic happens, when you render your Home component and useEffect
// goes to perform your axios request jest will automatically call your __mocks__/axios instead
wrapper = await renderer.create(<Home />);
});
await expect(wrapper.toJSON()).toMatchSnapshot();
});
it("renders error", async () => {
await act(async () => {
// You can also override your __mocks__/axios by doing the following and simulate a different
// response from your mocking axios
await axios.get.mockImplementationOnce(() =>
Promise.resolve({
status: 400,
statusText: "400",
headers: {},
config: {},
})
);
wrapper = await renderer.create(<Home />);
});
await expect(wrapper.toJSON()).toMatchSnapshot();
});
});
Now when you run npm run test your Home component will receive the data from your __mocks__/axios and render it as expected and you can perform all sorts of tests on it.
This is actually really cool!

Unable to use Dynamic data into react-native-chart-kit

I tried to render fetched data from the firestore and display them into react-native-chart-kit. However, I always face the below error:
invalidNumber: M0,0 L-Infinity,181 L64,181
I got data correctly from the database by this function:
const getweight = () =>
firebase
.firestore()
.collection("weights")
.orderBy("time")
.where("user", "==", "1")
.get()
.then((querySnapshot) => {
let result = [0];
querySnapshot.forEach((doc) => {
result.push(+doc.data().Weight);
});
setDateTracker(date);
if (result.length) {
setWeighTracker(result);
}
});
so, I got the array with the right data.
Then, I push data to the state below:
const [weightTracker, setWeighTracker] = useState([0]);
when I try to display data to the chart like below, I got error of invalid number
<LineChart
data={{
datasets: [
{
data: weightTracker.map((item) => {
return item.Weight;
}),
},
],
}}
width={Dimensions.get("window").width} // from react-native
height={220}
yAxisLabel=" KG "
//withVerticalLabels={false}
chartConfig={{
backgroundColor: "#e26a00",
backgroundGradientFrom: "#fb8c00",
backgroundGradientTo: "#ffa726",
decimalPlaces: 0, // optional, defaults to 2dp
color: (opacity = 1) => `rgba(255, 255, 255, ${opacity})`,
style: {
borderRadius: 1,
},
}}
bezier
style={{
marginVertical: 8,
borderRadius: 16,
}}
/>
I encountered the same error even when the data is with initial state of 0 . What fixed mine is to only display the chart once data is loaded.
You may add an if check like this before your chart code:
if (weightTracker?.length === 0) {
return (
<View style={styles.screen}>
<Text>No chart data to display!</Text>
</View>
);
}
return (...<your linechart code>)
For the if check to work, you also need to set the initial state of weightTracker to just an empty array.
Hope this helps.

The best way of tracking location in background using react-native + Expo in 2020

I want to create my own Endomono/Runtastic-like app using RN + expo (This app will be just for me, and I have android phone with pretty decent performance/battery life (Redmi note 7) so I don't worry about performance too much). I wanted to use all-in-one library for that, or just and library that allows me to execute some code each X seconds in background (and getAsyncLocation there). My point is just to send lat/lon data every X seconds to my backend HTTP django-rest-framework powered server.
I just spent whole day trying figure out any way to do that, I tried couple of libraries like this ones: react-native-background-geolocation, react-native-background-timer, react-native-background-job and few more. I followed step by step instalation guide, and I kept getting errors like: null is not an object (evaluating 'RNBackgroundTimer.setTimeout') .
I also tried this: I fixed some errors in this code (imports related), it seemed to work, but when I changed my GPS location using Fake GPS, and only one cast of didFocus functions appears in the console. Here's code:
import React from 'react';
import { EventEmitter } from 'fbemitter';
import { NavigationEvents } from 'react-navigation';
import { AppState, AsyncStorage, Platform, StyleSheet, Text, View, Button } from 'react-native';
import MapView from 'react-native-maps';
import * as Permissions from 'expo-permissions';
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import { FontAwesome, MaterialIcons } from '#expo/vector-icons';
const STORAGE_KEY = 'expo-home-locations';
const LOCATION_UPDATES_TASK = 'location-updates';
const locationEventsEmitter = new EventEmitter();
export default class MapScreen extends React.Component {
static navigationOptions = {
title: 'Background location',
};
mapViewRef = React.createRef();
state = {
accuracy: 4,
isTracking: false,
showsBackgroundLocationIndicator: false,
savedLocations: [],
initialRegion: null,
error: null,
};
didFocus = async () => {
console.log("Hello")
let { status } = await Permissions.askAsync(Permissions.LOCATION);
if (status !== 'granted') {
AppState.addEventListener('change', this.handleAppStateChange);
this.setState({
error:
'Location permissions are required in order to use this feature. You can manually enable them at any time in the "Location Services" section of the Settings app.',
});
return;
} else {
this.setState({ error: null });
}
const { coords } = await Location.getCurrentPositionAsync();
console.log(coords)
const isTracking = await Location.hasStartedLocationUpdatesAsync(LOCATION_UPDATES_TASK);
const task = (await TaskManager.getRegisteredTasksAsync()).find(
({ taskName }) => taskName === LOCATION_UPDATES_TASK
);
const savedLocations = await getSavedLocations();
const accuracy = (task && task.options.accuracy) || this.state.accuracy;
this.eventSubscription = locationEventsEmitter.addListener('update', locations => {
this.setState({ savedLocations: locations });
});
if (!isTracking) {
alert('Click `Start tracking` to start getting location updates.');
}
this.setState({
accuracy,
isTracking,
savedLocations,
initialRegion: {
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: 0.004,
longitudeDelta: 0.002,
},
});
};
handleAppStateChange = nextAppState => {
if (nextAppState !== 'active') {
return;
}
if (this.state.initialRegion) {
AppState.removeEventListener('change', this.handleAppStateChange);
return;
}
this.didFocus();
};
componentWillUnmount() {
if (this.eventSubscription) {
this.eventSubscription.remove();
}
AppState.removeEventListener('change', this.handleAppStateChange);
}
async startLocationUpdates(accuracy = this.state.accuracy) {
await Location.startLocationUpdatesAsync(LOCATION_UPDATES_TASK, {
accuracy,
showsBackgroundLocationIndicator: this.state.showsBackgroundLocationIndicator,
});
if (!this.state.isTracking) {
alert(
'Now you can send app to the background, go somewhere and come back here! You can even terminate the app and it will be woken up when the new significant location change comes out.'
);
}
this.setState({ isTracking: true });
}
async stopLocationUpdates() {
await Location.stopLocationUpdatesAsync(LOCATION_UPDATES_TASK);
this.setState({ isTracking: false });
}
clearLocations = async () => {
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify([]));
this.setState({ savedLocations: [] });
};
toggleTracking = async () => {
await AsyncStorage.removeItem(STORAGE_KEY);
if (this.state.isTracking) {
await this.stopLocationUpdates();
} else {
await this.startLocationUpdates();
}
this.setState({ savedLocations: [] });
};
onAccuracyChange = () => {
const next = Location.Accuracy[this.state.accuracy + 1];
const accuracy = next ? Location.Accuracy[next] : Location.Accuracy.Lowest;
this.setState({ accuracy });
if (this.state.isTracking) {
// Restart background task with the new accuracy.
this.startLocationUpdates(accuracy);
}
};
toggleLocationIndicator = async () => {
const showsBackgroundLocationIndicator = !this.state.showsBackgroundLocationIndicator;
this.setState({ showsBackgroundLocationIndicator }, async () => {
if (this.state.isTracking) {
await this.startLocationUpdates();
}
});
};
onCenterMap = async () => {
const { coords } = await Location.getCurrentPositionAsync();
const mapView = this.mapViewRef.current;
if (mapView) {
mapView.animateToRegion({
latitude: coords.latitude,
longitude: coords.longitude,
latitudeDelta: 0.004,
longitudeDelta: 0.002,
});
}
};
renderPolyline() {
const { savedLocations } = this.state;
if (savedLocations.length === 0) {
return null;
}
return (
<MapView.Polyline
coordinates={savedLocations}
strokeWidth={3}
strokeColor={"black"}
/>
);
}
render() {
if (this.state.error) {
return <Text style={styles.errorText}>{this.state.error}</Text>;
}
if (!this.state.initialRegion) {
return <NavigationEvents onDidFocus={this.didFocus} />;
}
return (
<View style={styles.screen}>
<MapView
ref={this.mapViewRef}
style={styles.mapView}
initialRegion={this.state.initialRegion}
showsUserLocation>
{this.renderPolyline()}
</MapView>
<View style={styles.buttons} pointerEvents="box-none">
<View style={styles.topButtons}>
<View style={styles.buttonsColumn}>
{Platform.OS === 'android' ? null : (
<Button style={styles.button} onPress={this.toggleLocationIndicator} title="background/indicator">
<Text>{this.state.showsBackgroundLocationIndicator ? 'Hide' : 'Show'}</Text>
<Text> background </Text>
<FontAwesome name="location-arrow" size={20} color="white" />
<Text> indicator</Text>
</Button>
)}
</View>
<View style={styles.buttonsColumn}>
<Button style={styles.button} onPress={this.onCenterMap} title="my location">
<MaterialIcons name="my-location" size={20} color="white" />
</Button>
</View>
</View>
<View style={styles.bottomButtons}>
<Button style={styles.button} onPress={this.clearLocations} title="clear locations">
Clear locations
</Button>
<Button style={styles.button} onPress={this.toggleTracking} title="start-stop tracking">
{this.state.isTracking ? 'Stop tracking' : 'Start tracking'}
</Button>
</View>
</View>
</View>
);
}
}
async function getSavedLocations() {
try {
const item = await AsyncStorage.getItem(STORAGE_KEY);
return item ? JSON.parse(item) : [];
} catch (e) {
return [];
}
}
if (Platform.OS !== 'android') {
TaskManager.defineTask(LOCATION_UPDATES_TASK, async ({ data: { locations } }) => {
if (locations && locations.length > 0) {
const savedLocations = await getSavedLocations();
const newLocations = locations.map(({ coords }) => ({
latitude: coords.latitude,
longitude: coords.longitude,
}));
savedLocations.push(...newLocations);
await AsyncStorage.setItem(STORAGE_KEY, JSON.stringify(savedLocations));
locationEventsEmitter.emit('update', savedLocations);
}
});
}
const styles = StyleSheet.create({
screen: {
flex: 1,
},
mapView: {
flex: 1,
},
buttons: {
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between',
padding: 10,
position: 'absolute',
top: 0,
right: 0,
bottom: 0,
left: 0,
},
topButtons: {
flexDirection: 'row',
justifyContent: 'space-between',
},
bottomButtons: {
flexDirection: 'column',
alignItems: 'flex-end',
},
buttonsColumn: {
flexDirection: 'column',
alignItems: 'flex-start',
},
button: {
paddingVertical: 5,
paddingHorizontal: 10,
marginVertical: 5,
},
errorText: {
fontSize: 15,
color: 'rgba(0,0,0,0.7)',
margin: 20,
},
});
If you know any way to easily complete my target (of sending simple HTTP GET with location from background of Expo + RN app to my DRF backend) please let me know.
If you're using Expo you can simply use expo-task-manager and expo-location to get background location updates.
Here's a simplified version that I'm using (and it's working for sure on Android) on the App I'm currently developing:
import * as Location from 'expo-location';
import * as TaskManager from 'expo-task-manager';
import axios from 'axios';
const TASK_FETCH_LOCATION = 'TASK_FETCH_LOCATION';
// 1 define the task passing its name and a callback that will be called whenever the location changes
TaskManager.defineTask(TASK_FETCH_LOCATION, async ({ data: { locations }, error }) => {
if (error) {
console.error(error);
return;
}
const [location] = locations;
try {
const url = `https://<your-api-endpoint>`;
await axios.post(url, { location }); // you should use post instead of get to persist data on the backend
} catch (err) {
console.error(err);
}
});
// 2 start the task
Location.startLocationUpdatesAsync(TASK_FETCH_LOCATION, {
accuracy: Location.Accuracy.Highest,
distanceInterval: 1, // minimum change (in meters) betweens updates
deferredUpdatesInterval: 1000, // minimum interval (in milliseconds) between updates
// foregroundService is how you get the task to be updated as often as would be if the app was open
foregroundService: {
notificationTitle: 'Using your location',
notificationBody: 'To turn off, go back to the app and switch something off.',
},
});
// 3 when you're done, stop it
Location.hasStartedLocationUpdatesAsync(TASK_FETCH_LOCATION).then((value) => {
if (value) {
Location.stopLocationUpdatesAsync(TASK_FETCH_LOCATION);
}
});
It doesn't necessarily work with Expo, but if "eject" your project or start with the React Native CLI (via react-native init) then you could use an Android specific React Native "NativeModule" to accomplish your goal. I like using the react-native-location package, which has great support on iOS for background location updates, but on Android there is a bug currently. I put together an example project which has the necessary Android specific code inside a NativeModule you could use to start from:
https://github.com/andersryanc/ReactNative-LocationSample

Accessing state functions from a list item on a render row nested onPress

I am trying to access one of my actions from within the my row onPress function but the issue is in the onPress it is out of scope from the rest of the state.
My question is how do I access the state functions to call from within my onPress method.
import {planLocalesFetch, localeDelete} from '../actions';
import LocaleListItem from './LocaleListItem';
import Swipeout from 'react-native-swipeout';
class PlanLocalesList extends Component {
// all the state code is here
renderRow(planLocale) {
let swipeBtns = [{
text: 'Delete',
fontWeight: 'bold',
backgroundColor: 'red',
onPress: () => {
axios.delete(`http://localhost:3000/locales/${planLocale.id}`, { params: {
locale_id: planLocale.id }});
this.props.planLocalesFetch(plan); // error is that this does not exist in this scope;
}
}];
return (
<Swipeout right={swipeBtns}
backgroundColor= 'transparent'>
<View>
<LocaleListItem planLocale={planLocale} />
</View>
</Swipeout>
)
}
render () {
return (
<View style={{flex: 1}}>
<ListView
dataSource={this.dataSource}
renderRow={this.renderRow.bind(this)}
/>
</View>
);
}
}
const mapStateToProps = state => {
const plan = state.planLocales.plan
const planLocales = _.map(state.planLocales.locales, (val, uid) => {
return { ...val, uid };
});
return { planLocales, plan};
};
export default connect(mapStateToProps, {planLocalesFetch, localeDelete})(PlanLocalesList);
Here is the action to fetch the data for the list.
export const planLocalesFetch = (plan) => {
return (dispatch, state) => {
if (plan) {
state().planForm.currentPlan = plan;
}
var plan_id = state().planForm.currentPlan.id;
axios.get(`http://localhost:3000/plans/${plan_id}`).then((response) => {
dispatch({type: PLAN_LOCALES_FETCH, payload: response.data})
});
};
};
The problem I am having is the this.props.planLocalesFetch(plan); does not exist in the nested onPress scope.
fix using the .then statement
let swipeBtns = [{
text: 'Delete',
fontWeight: 'bold',
backgroundColor: 'red',
onPress: () => {
axios.delete(`http://localhost:3000/locales/${planLocale.id}`, { params: {
locale_id: planLocale.id }}).then(() => {
this.props.planLocalesFetch();
})