I am upgrading a react-native app from version react-navigation V4.x to version 6.x. I have this piece of code
export const AppNavigationContainer = createAppContainer(
createNavigator(
AppContainer as any, //this is the navigation view which will be dislpayed.
StackRouter(NavigatorRoutes, NavigatorConfig), // the routers
NavigatorConfig // the configuration
)) as unknown as React.ComponentType<AppContainerProps>;
which I am trying to convert into version 6.x
I am aware that the createAppContainer will be replaced by <NavigationContainer><NavigationContainer /> , Which will take the custom navigator, but I am not able to understand how to convert this piece of code which creates the custom navigator. The router being passed as the second parameter has been converted, the only problem is how to get it all together using the new custom hook useNavigationBuilder() provided.
Related
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.
I have problem about navigation from other script (screen)... I implemented navigation in App.js (with createStackNavigator and with screens). Everything works fine when I want to navigate (with OnPress{() => navigate("someScreen")} to screen which is defined in this script (App.js).
But, when I want to use that navigation from other script (outside of App.js), let's say in "NewPage.js"
which has own "export default class NewPage..." and inside I have button element which task is to navigate "onPress" to screen which is defined in the App.js stackNavigator...
I know that I can't use anymore navigate("pageName") because navigation isn't implemented in this script and I tried with import { NavigationActions } from 'react-native' and inside of button element I tried with code: "this.props.navigation.navigate('somePage')" and it's not working.
So I don't know how to use navigation property from other script in which isn't implemented navigation, how to reference/export/import that property?
Here is code App.js script: https://pastebin.com/tLEFdQrE and NewPage.js script: https://pastebin.com/aVQGiinJ
This code is short so you can easily see what I want and what is the problem...
Thank you in advance!
Use this for better navigation among screen as compared to default navigation this is the better one for navigating among the screens. We mostly use this than other navigator
https://github.com/aksonov/react-native-router-flux
You should import your pages [using the names of the exported components, not the names of the js files] into your App.js.
For example, I stored my pages in a folder called 'screens' so when I imported my 'Home' screen, I used
import HomeScreen from './screens/HomeScreen.js';
which was further referenced as
Home: HomeScreen,
Good luck!
UPDATE:
react-navigation web support is done. follow this:
https://reactnavigation.org/docs/en/web-support.html
ORIGIN:
I try to share my code between react-native and web.
when I try react-native-web, it works well.
but there is only one question, how to access the specific screen from URL?
I read the react-navigation docs, there nothing about that.
and react-router-native can catch the web URL,
but it has navigator likes StackNavigator/DrawerNavigator.
and idea about that?
I'm not sure what the case was at the time you posted this question, but you definitely can use react-navigation with web now adays.
Now with Linking we can Handle deep links in React Native apps on Android and iOS, plus
Enable URL integration in browser when using on web.
The NavigationContainer component takes in a linking prop which allows you to map out your routes.
const linking = {
prefixes: ['https://mychat.com', 'mychat://'],
config: {
screens: {
Chat: 'feed/:sort',
Profile: 'user',
},
},
};
function App() {
return (
<NavigationContainer linking={linking} fallback={<Text>Loading...</Text>}>
{/* content */}
</NavigationContainer>
);
}
Once we establish what all of the routes or "links" are in our app we can start using Link components to navigate just like in a normal react web application if you used react-router-dom.
import { Link } from '#react-navigation/native';
// ...
function Home() {
return <Link to="/profile/jane">Go to Jane's profile</Link>;
}
These link components should work on both mobile, and web versions.
https://reactnavigation.org/docs/configuring-links/
https://reactnavigation.org/docs/deep-linking/
https://reactnavigation.org/docs/link
I don't think it's possible as ReactNavigation is using an internal state object. Remember, it's mobile framework, it has no concept of URL routing.
I also wanted to point out that even though RN claims web support you will need to be careful with component selection as not all the behaviours are identical (from memory, FlatList does not support touch scroll)
I keep running into undefined is not an object (evaluating 'RCCManager.setRootController') when trying to use react-native-navigation.
I tried to follow suit with https://github.com/junedomingo/movieapp but hit this when it tries to load the project in the Expo app.
I've modified my App.js generated by Expo to look like this:
import HomeScreen from './screens/HomeScreen'
Navigation.registerComponent('screens.HomeScreen', () => HomeScreen)
class App extends React.Component {
constructor(props) {
super(props)
this.startApp()
}
startApp() {
Navigation.startTabBasedApp({
tabs: [
{
label: 'One',
screen: 'screens.HomeScreen',
title: 'Screen One'
},
]
})
}
}
const app = new App()
That's a bit boiled down, but I think those are the essential bits. I feel like I'm not handing things off from rnn to Expo the way Expo is expecting.
Any idea how to get rnn running in Expo? If there's an example repo I can play with, that would be great. I'm sure I can get rnn working outside Expo, so vanilla rnn examples probably won't help much.
Because react-native-navigation has native dependencies and need you to add custom native code you can not use it with Expo out of the package.
One option is to detach your project and use the package like that. This has a side effect of loosing some expo properties.
Another option is (if you are not too deep in the project) creating a new app with react-native-cli and moving your code to that project. This has side effect of not being able to use expo api.
Third option is to use a navigation package that doesn't depend on native code. Some of the most popular options are react-navigation and react-native-router-flux.
I have followed –or tried to– several posts on how to do it, including the airbnb enzyme's guide for (separatedly) react-native and jest. (E.g: https://medium.com/#childsmaidment/testing-react-native-components-with-enzyme-d46bf735540#.6sxq10kgt, https://blog.callstack.io/unit-testing-react-native-with-the-new-jest-i-snapshots-come-into-play-68ba19b1b9fe#.4iqylmqh5 or How to use Jest with React Native)
But I keep getting lots of warnings (I have multiple set of concurrent tests) whenever I try to render (not mount, it crashes) any native component. Warnings are always about a native prop not being recognised.
Warning: Unknown props `focus`, `secureTextEntry` on <TextInput> tag. Remove these props from the element.
in TextInput (created by TextInput)
in TextInput (created by PasswordInput)
Anyone who has a set up working, recognises how to remove the warning or how to solve it?
Thanks
So I know this is a bit old but I was having issues with Jest, Enzyme, and React Native and I found this post - hopefully this solution will help.
To start with - Enzyme doesn't support mounting React Native and only supports shallow rendering. This wasn't good enough for me as I needed end-to-end tests from the component to the api which lead me to react-native-mock-render. What this does is allow us to run react native inside a browser environment which let's us test using Enzyme - all the calls for React Native and the components work as you would expect.
To set this up you'll need to install JSDOM, react-native-mock-render, Enzyme 3.0+, and Jest 20.0.0+. And then inside your jest setup file (which is specified in your package.json) include the following code:
const { JSDOM } = require('jsdom');
const jsdom = new JSDOM();
const { window } = jsdom;
function copyProps(src, target) {
const props = Object.getOwnPropertyNames(src)
.filter(prop => typeof target[prop] === 'undefined')
.map(prop => Object.getOwnPropertyDescriptor(src, prop));
Object.defineProperties(target, props);
}
global.window = window;
global.document = window.document;
global.navigator = {
userAgent: 'node.js',
};
copyProps(window, global);
// Setup adapter to work with enzyme 3.2.0
const Enzyme = require('enzyme');
const Adapter = require('enzyme-adapter-react-16');
Enzyme.configure({ adapter: new Adapter() });
// Ignore React Web errors when using React Native
console.error = (message) => {
return message;
};
require('react-native-mock-render/mock');
And that's it - you're all setup to mount components in Enzyme and test them.
If you want to see a full sample check out react-native-mock-render-example. This is working with React 16, React Native 0.51, and Enzyme 3.2.
In order to unit test your component with jest you can use enzyme-to-json
npm install --save enzyme-to-json
then your test would look like this:
import { shallow } from 'enzyme';
import { shallowToJson } from 'enzyme-to-json';
import MyComponent from './MyComponent';
it('should render component', => {
expect(shallowToJson(shallow(<MyComponent />))).toMatchSnapshot();
});
I'm not sure regarding your case with react-native.
I can share my case of using jest + enzyme with standard react.
When I needed to test some component and isolate it from others I used jest.mock, e.g.
jest.mock('../ComponentToBeMocked', () => {
return () => null;
});
Initially I found examples when the second argument (a function) should return just a string representing a name of the mocked component. But in that case I saw that distracting Unknown props warning.