I am trying to decide on the best way to set up routing in my React Native Web project. I am using expo and followed this guide to use Next JS https://docs.expo.io/versions/latest/guides/using-nextjs/ so I have App.js like this:
import index from "./pages/index";
import alternate from "./pages/alternate";
import { createStackNavigator } from "react-navigation-stack";
import { createAppContainer } from "react-navigation";
const AppNavigator = createStackNavigator(
{
index,
alternate
},
{
initialRouteName: "index"
}
);
const AppContainer = createAppContainer(AppNavigator);
export default AppContainer;
My concern is how best to handle routing. I have my index.js page setup like this currently.
import * as React from 'react'
import { StyleSheet, Button, Text, View } from 'react-native'
export default function App ({navigation}) {
return (
<View style={styles.container}>
{/* Native route */}
<Button
title="Go to Details"
onPress={() => navigation.navigate("alternate")}
/>
{/* Web route */}
<Text style={styles.link} accessibilityRole="link" href={`/alternate`}>
A universal link
</Text>
</View>
);
}
As you can see this is currently requiring separate code to render a Native vs Web route. I am wondering what is the best way to handle this sort of rendering. I looked into using React Navigation for web and wouldn't be opposed to this but it seems like I should probably stick with the Next Router.
Thanks in advance for any advice on handling conditional rendering like this.
Use reactnavigation web support for that
https://reactnavigation.org/docs/en/web-support.html
import { createSwitchNavigator } from "#react-navigation/core";
import { createBrowserApp } from "#react-navigation/web";
const MyNavigator = createSwitchNavigator(routes);
const App = createBrowserApp(MyNavigator);
// now you can render "App" normally
There is import { Platform } from 'react-native':
{Platform.OS === 'web' ? (
<Text
style={styles.link}
accessibilityRole="link"
href={`/alternate`}
>
A universal link
</Text>
) : (
<Button
title="Go to Details"
onPress={() => navigation.navigate("alternate")}
/>
)}
Related
React-native styling using Nativewind works fine if the styling is done at App.Js. Like here:
<NavigationContainer>
<View>
<Text className = "text-red-500">Hello</Text>
</View>
</NavigationContainer>
But if the styling is done at component level, then it doesn't work anymore.
return (
<NavigationContainer>
<HomeScreen/>
</NavigationContainer>
);
HomeScreen Component:
import { View, Text } from 'react-native'
import React from 'react'
const HomeScreen = () => {
return (
<View>
<Text className = "text-red-500">Hello</Text>
</View>
)
}
export default HomeScreen
You'll need to tell nativewind the locations of where your components reside by adding this to your tailwind.config.ts
content: ["./App.{js,jsx,ts,tsx}", "./<custom directory such as src>/**/*.{js,jsx,ts,tsx}"],
reference: https://www.nativewind.dev/quick-starts/react-native-cli
If you setup folder in tailwind.config.js and still not work then delete nodemodule then install it again and it will work.
This works for me:
content: ["./App.{js,jsx,ts,tsx}", "./<custom directory such as src>/**/*.{js,jsx,ts,tsx}"]
I'd like to use the React Navigation v5 (Drawer navigation) with Next.js but I have a question about their integration.
In short: React Navigation (Drawer navigation) based on the React Navigation Screens component.
It conditionally renders the correct Screen.
The problem is: Next.js has it's own routing system based on the Folder structure. eg. each file in /pages folder automatically generates an appropriate route so I can't add these files as a React Navigation Screen (at least I'm not sure it's possible at all)
How to make these tools to work together and save the Next.js SSR feature?
Example of the React Navigation Drawer:
import * as React from 'react';
import { Button, View } from 'react-native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import { NavigationContainer } from '#react-navigation/native';
function HomeScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button
onPress={() => navigation.navigate('Notifications')}
title="Go to notifications"
/>
</View>
);
}
function NotificationsScreen({ navigation }) {
return (
<View style={{ flex: 1, alignItems: 'center', justifyContent: 'center' }}>
<Button onPress={() => navigation.goBack()} title="Go back home" />
</View>
);
}
const Drawer = createDrawerNavigator();
export default function App() {
return (
<NavigationContainer>
<Drawer.Navigator initialRouteName="Home">
<Drawer.Screen name="Home" component={HomeScreen} />
<Drawer.Screen name="Notifications" component={NotificationsScreen} />
</Drawer.Navigator>
</NavigationContainer>
);
}
Thanks for any help!
You should use file based routing system from Nextjs on web and do your own navigation on mobile using React Navigation.
Below is my approach,
// this is how your directory might look like
- pages/
- index.tsx // this is your entry point for web
- about.tsx
App.tsx // this is your entry point for native
// pages/index.tsx
import React from 'react';
import { Text, View } from 'react-native';
const Home: React.FC = () => (
<View>
<Text>Welcome to Expo + Next.js 👋</Text>
</View>
);
export default Home;
// pages/about.tsx
import React from 'react';
import { Text, View } from 'react-native';
const About: React.FC = () => (
<View>
<Text>This is about page!</Text>
</View>
);
export default About;
Define your navigator for native app in App.tsx, it will only work on mobile so it doesn't have to be the same as what you have in pages/ folder. (actually if you only want your app run in browser, you don't need it at all.
Nextjs will handle all the route things, SSR etc... just like a normal Nextjs app when you run it in a browser.
// App.tsx
import React from 'react';
import { NavigationContainer } from '#react-navigation/native';
import { createDrawerNavigator } from '#react-navigation/drawer';
import Home from '../pages/index';
import About from '../pages/about';
const Drawer = createDrawerNavigator();
const App: React.FC = () => (
<NavigationContainer>
<Drawer.Navigator>
<Drawer.Screen name="Home" component={Home} />
<Drawer.Screen name="About" component={About} />
</Drawer.Navigator>
</NavigationContainer>
);
export default App;
The important thing is how should you change routes when you have your navigation on native app but an automatically routing system on web?
There is a package to solve this expo-next-react-navigation, check the documentation for details! Make sure you're using the correct version of this package, if you're using React Navigation 5, you should install expo-next-react-navigation#1.1.6 at this moment.
And here is an example, it should work on both platforms,
import React from 'react';
import { FlatList, Text } from 'react-native';
import { Link } from 'expo-next-react-navigation';
const links = [
{ key: 'home', route: '' },
{ key: 'about', route: 'about' },
];
const Links: React.FC = () => (
<FlatList
data={links}
renderItem={({ item }) => (
<Link routeName={item.route}>
{item.key}
</Link>
)}
/>
);
export default Links;
I have a website written with React (https://new.sacatucita.com/).
On my website, I have a search bar using react-select (https://github.com/JedWatson/react-select).
I want to make an application showing my website with React Native, so I have this code:
import React from "react";
import { WebView } from "react-native-webview";
export default function App() {
return (
<WebView
originWhitelist={["*"]}
source={{ uri: "https://new.sacatucita.com/" }}
/>
);
}
The problem is that when I open my application and click on the search bar, the keyboard and results do not show. It appears that the click has no effect. I need to first click elsewhere (like on the title text for example), and then the search bah will work.
I already tried to select the webview with the ref:
ref={ref => {
const e = ref && ref.webViewRef && ref.webViewRef.current;
e && e.focus();
}}
And to click injecting HTML:
const js = `
const e = document.getElementsByTagName("h1")[0];
e.click();
`;
export default function App() {
return (
<WebView
originWhitelist={["*"]}
source={{ uri: url }}
injectedJavaScript={js}
/>
);
}
I found out that the problem is only present on android devices.
Is there a solution?
When you do this, the keyboard will come out normally.
I made a link so you could test it yourself.
import React, {Component} from 'react';
import {WebView} from 'react-native';
class App extends Component {
render() {
return (
<WebView
source={{uri: 'https://new.sacatucita.com/'}}
style={{marginTop: 20}}
/>
);
}
}
export default App;
React native : How can I custom tab bar like image below??
1) you can use this library to create tabs react-native-scrollable-tab-view.
2) Then it has a prop (renderTabBar) here you can pass your own custom tab bar.
<ScrollableTabView renderTabBar={() => <DefaultTabBar tabStyle={{color: 'red'}} />} />
one tip that i am giving.
make a file name it CustomTabBar copy all the code from libraries DefaultTabBar and past it in your CustomTabBar.
now change its designs the way you want it to be and use it like this. This way you will have to do the least amount of work.
<ScrollableTabView renderTabBar={() => <CustomTabBar/>} />
Maybe this is the solution you need
1, Install: switch-react-native
npm i switch-react-native
2, Using lib:
import React, { Component } from 'react';
import { View } from 'react-native';
import { Switch } from 'switch-react-native';
class SwitchExample extends Component {
render() {
return (
<View>
<Switch
height={40}
width={300}
activeText={`Active Text`}
inActiveText={`InActive Text`}
onValueChange={(value: any) => console.log(value)}
/>
</View>
);
}
}
I am new to react and react native.
I am trying to set up a simple app, using this tutorial
https://github.com/aksonov/react-native-router-flux/blob/master/docs/MINI_TUTORIAL.md
I have set up my app with this command
create-react-native-app my-project
I start the app and see it in expo on my phone.
Then
npm i react-native-router-flux --save
I replace the contents of App.js with all the code from that tutorial. I also create the required PageOne.js and PageTwo.js.
I then get an immediate error on my phone.
[react-native-router-flux] props should be defined
assert
c:\my path...\react-native-router-flux\src\Util.js#34:10
How do I define these props? What do I need to do to get this working?
Extras!
The code is exactly as in that tutorial,
App.js
import React, { Component } from 'react';
import { Router, Scene } from 'react-native-router-flux';
import PageOne from './PageOne';
import PageTwo from './PageTwo';
export default class App extends Component {
render() {
return (
<Router>
<Scene key="root">
<Scene key="pageOne" component={PageOne} title="PageOne" initial={true} />
<Scene key="pageTwo" component={PageTwo} title="PageTwo" />
</Scene>
</Router>
)
}
}
PageOne.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { Actions } from 'react-native-router-flux';
export default class PageOne extends Component {
render() {
return (
<View style={{margin: 128}}>
<Text onPress={Actions.pageTwo}>This is PageOne! </Text>
</View>
)
}
}
PageTwo.js
import React, { Component } from 'react';
import { View, Text } from 'react-native';
import { Actions } from 'react-native-router-flux';
export default class PageTwo extends Component {
render() {
return (
<View style={{margin: 128}}>
<Text onPress={Actions.pageOne}>This is PageTwo!</Text>
</View>
)
}
}
I don't really have a conclusive answer. Perhaps just being new to a lot of different moving parts had caused something to get out of line.
I updated some magic numbers in package.json and app.json according to the upgrade table on this page
https://github.com/react-community/create-react-native-app/blob/master/VERSIONS.md
and things started to work again.
I suppose that some of my thrashing around installing various react things had gotten the installed versions out of step. Perhaps if I really understood the ecosystem it would seem clear to me but it feels like a bunch of string and bailing wire at the moment!