Detect when a ShapeSource finished loading its url GeoJson data in react-native - react-native

I'm using the react-native-mapbox-gl/maps library in my react-native app, and I'm trying to show a <MapboxGL.ShapeSource that loads a GeoJson source, like this.
I have this code that is working, however, as the GeoJson data takes a while to finish loading, I couldn't find a way to show to the user if the data is loading or it is ready, with a Spinner for instance.
My question is: is there a way to detect when the MapboxGL.ShapeSource finishes loading its data or when the MapboxGL.FillLayer is visible in the Map?
import React from 'react';
import MapboxGL from '#react-native-mapbox-gl/maps';
const DemographicsMapLayer = () => {
const dataSourceUri = 'https://gist.githubusercontent.com/victor0402/dc3b40195a55ed998a45189b7fb4939b/raw/d7021c29637621e07a82e771d89ea278de48fb99/demographics.json'
return (
<MapboxGL.ShapeSource id={'demographicSourceID'} url={dataSourceUri}>}
<MapboxGL.FillLayer
id={'Millenials'}
key={'Millenials'}
sourceID={'demographicSourceID'}
filter={['==', '$type', 'Polygon']}
style={{ fillOpacity: 0.4 }}
onLayout={e => console.log('[FillLayer] onLayout', e)}
/>
</MapboxGL.ShapeSource>
Version of the lib in my package.json file:
"#react-native-mapbox-gl/maps": "^8.1.0-rc.9",
I tried using the onLayout event in both FillLayer and ShapeSource, but couldn't get useful information, maybe I'm looking the wrong thing.

Related

React Navigation: Pushing to stack in a React Native Webview

I have a Component that renders a Webview, of which there are links. For example, if I have something like:
export const About = () => {
return (
<SafeAreaView edges={['right', 'top', 'left']} style={{ flex: 1 }}>
<Webview url={`${BASE_URL}/about`} />
</SafeAreaView>
)
}
export default About
Let's say that on the /about page, we have a link to /faq. As things currently stand, if I click on the link to /faq, the page will be rendered in that current Webview.
My desired behavior is for the /faq to put on the navigation stack so I can take advantage of the back button in the header. I don't know how to accomplish this. I don't have access to the link to /faq via React Native (see code snippet above) so I can't just add an onClick that pushes a page to the stack.
Another thing I was exploring was setting up some linking configurations so I can link /faq to /about, and so the routing would recognize that. No idea if I was going down a good path there. Please forgive me if I've mixed up concepts, my understanding of the React Native ecosystem and React Navigation is still very raw. Thank you for your time.

Why doesn't ref.current.focus() work when running tests via the #testing-library/react-native libary?

I'm attempting to write some tests for my react native app. A component in my app focuses a TextInput after a parent Pressable receives a press. I'm using a ref to identify and focus the TextInput element.
My desired functionality works just fine when running my app through expo, but my test is failing because it seems that the onFocus event is not being called.
Why isn't ref.current.focus() being called when running tests via the #testing-library/react-native library?
Here's my code:
Foo.js
import {Pressable, TextInput} from "react-native";
import {useRef} from "react";
const Foo = (props) => {
const inputRef = useRef()
return (
<Pressable testID={"pressable"} onPress={() => inputRef.current.focus()}>
<TextInput ref={inputRef} testID={"input"} onFocus={props.onFocus} />
</Pressable>
)
}
export default Foo;
Foo.test.js
import { render, screen, fireEvent } from '#testing-library/react-native';
import Foo from "./foo";
test('onFocus is called after press', () => {
const mockFocus = jest.fn();
render(<Foo onFocus={mockFocus} />)
// fireEvent(screen.getByTestId("input"), 'focus');
fireEvent.press(screen.getByTestId("pressable"));
expect(mockFocus).toHaveBeenCalled()
});
This test fails with the following message:
Error: expect(jest.fn()).toHaveBeenCalled()
Expected number of calls: >= 1
Received number of calls: 0
I created an issue on the RNTL GitHub page and received a response from a contributor. Copying and pasting here for easy reference for anyone who might stumble upon this thread.
This is expected as React Test Renderer which we use for rendering
does not support refs. Check #1006 for more details.
Since the behaviour of focus() triggering onFocus event would probably
involve roundtrip to native side (from JS side), then you actually
cannot test such behaviour using RNTL as we do not run native code (see
here for details).
That leaves you with following options:
Call fireEvent.focus to manually trigger onFocus on relevant
TextInput. Recommended in case focus assertion would be a part of a
step in a bigger test.
Use createNodeMock to pass ref creating function to render method, More details here. Recommended in case you
just want to assert pressing button triggers onFocus.

React-native-web Multi-Platform Setup using Expo 44 + Typescript

What is the simplest way to implement Multi-Platform Setup for a component in Expo. I have tried mamy diferent ways.. it was working on web but it is failing on Native and failing with Jest & #testing-library/react-native. Ideally I would like the least amount of custom config etc (do not want to eject). I expect the file structure to look like this:
Component
|- index.tsx
|- Component.native.tsx
|- Component.web.tsx
I am not sure how to do the index.tsx. I saw someone say something like this would work:
// index.tsx
// #ts-ignore
export { default } from "Component"
this didn't work so I did
// index.tsx
// #ts-ignore
export { default } from "./Component"
This worked for web, but the jest test said
Cannot find './Component'
However, Jest was able to find:
'./Component.mobile.tsx'
'./Component.web.tsx'
I tried:
// index.tsx
// #ts-ignore
import Component from "./Component";
export default Component
and the tests was the same
and the native emulator said:
Unable to resolve module ./Component
I tried using lazy loading but this does not work on web.
import { lazy, Suspense } from "react";
import { Platform } from "react-native";
import Loading from "../../components/Loading";
import { ComponentType } from "./types";
const Web = lazy(() => import("./Component.web"));
const Mobile = lazy(() => import("./Component.mobile"));
const Component: ComponentType = (props) => {
const isWeb = Platform.OS === "web";
return (
<Suspense fallback={<Loading message="Loading Component" />}>
{isWeb ? <Web {...props} /> : <Mobile {...props} />}
</Suspense>
);
};
export default Component
Questions
how to use diferent files for components depending on platform (exlude other files from build)
how to make it ok with ts in vscode
Using Expo 44. Thanks
I would use named exports. So begin by having the same component name in both files. Next I would have one file called Component.tsx and the other Component.native.tsx. That will be enough to allow the bundler to pull the native for native and the other for non-native (in other words web). That should be all you need.

React native getInitialURL not nullify after use

After using Linking.getInitialURL() the URL stay there.
I am using react-native-router-flux to navigate.
when users log out I run
import { NativeModules } from 'react-native';
NativeModules.DevSettings.reload()
What happens is the react-navigation do Linking.getInitialURL()
and if there any result so it navigates automatically to the page.
how to reset Linking.getInitialURL() after use ?
happens only on android
React Navigation 5 provides an option to specify a custom getInitialURL method which you can use:
<NavigationContainer
linking={{
// ... linking config
getInitialURL() {
return YourCustomModule.getInitialURL();
},
}}
>
{/* content */}
</NavigationContainer>
https://reactnavigation.org/docs/navigation-container/#linkinggetinitialurl
For the implementation, since you're reloading the whole JS, the code cannot be in JS as the state is lost on reload. You'll need to write a custom native module where you can clear the initial URL when reloading.

WebXR not working in React Native WebView Component

How to make https://xr-spinosaurus.glitch.me/ work in a React Native WebView Component?
import React, { Component } from 'react';
import { WebView } from 'react-native';
export default class MyWeb extends Component {
render() {
return (
<WebView
source={{uri: 'https://xr-spinosaurus.glitch.me/'}}
style={{marginTop: 20}}
/>
);
}
}
Right now adding this to react-native only shows VR option but not AR option.
If you access the link directly you could see VR and AR options but I couldn't find the AR option when run in a Web View component inside React-Native
But the same AR option is available if I directly access the link on an ARCore supported Device.
How to make this code also show the AR option in React-Native?
AFAIK that is currently not possible, since the Android WebView doesn't (yet) support the WebXR Device API (and neither on apple). Source: https://developer.mozilla.org/en-US/docs/Web/API/WebXR_Device_API
I've been running into the same problem, hopefully support will be added soon, but for now there's not much you can do.