Home > other >  Expo, React Native: Issue with URL & Refreshing
Expo, React Native: Issue with URL & Refreshing

Time:10-26

Hey guys I am having a small issue, I have been building a test add for the following platforms [ Web, Phones, Desktop ]

The following frameworks I am using,

  • Expo

  • React Native

  • React Native Navigation

My issue is when on the PWA build after building the app, I am having an issue where if a user wants to directly navigate to a specific path OR refreshes the page the website returns 404 when clearly works in the following example GIF's below.

-- Expo dev tool: https://gyazo.com/0abc4161810cb14e74543b3dcb854b49

-- After running expo build:web then after expo finished building the PWA I run npx serve web-build : https://gyazo.com/ed699dcc4b13830647552b07ee112c62

I am not sure what added config I need to do or what? I have been searching my issue and cannot find anything

If anyone can help would be you guys !!

ADDED NOTE >>>

I haven't coded a login system or any type of cashing etc this is just components with one page having a button that sends a user to a page(Profile)

App.js

import LoginScreen from './views/login'
import ProfileScreen from './views/profile'

export default function App() {
  return React.createElement(
    (Platform.OS == 'web') ? web_navigator : mobile_navigator
  );
}

function mobile_navigator() {
  const Tab = createBottomTabNavigator();
  return (
    <NavigationContainer>
        <Tab.Navigator
        screenOptions={{
            headerShown: false,
            tabBarStyle: {
              backgroundColor: "#242629",
              borderTopWidth: 0
            },
            tabBarOptions: {
              showLabel: false,
            }
        }}
        
        >
  
          <Tab.Screen name="Login" component={LoginScreen} />

          <Tab.Screen name="Profile" component={ProfileScreen} />
        </Tab.Navigator>
    </NavigationContainer>
  );
}

function web_navigator() {
  const Stack = createStackNavigator();
  
  return (
      <NavigationContainer linking={{
        config: {
          screens: {
            Login: "/",
            Profile: "/Profile/:Username?"
          }
        },
        }}>
        <Stack.Navigator
        screenOptions={{
          headerShown: false
        }}>
          <Stack.Screen name="Login" component={LoginScreen} />
          <Stack.Screen name="Profile" component={ProfileScreen} />
        </Stack.Navigator>
      </NavigationContainer>
  );
}

Login.js

    const Login = ({navigation}) => {
      const [userName, setUserName] = useState('');
      const [userPassword, setUserPassword] = useState('');
    
        return (
          <View style={styles.Body} >
    
            {Platform.OS === 'web' ?
          
            <View style={styles.Body_left} >
              <Image 
                source={require("../assets/LeftPanel3.png")} 
                style={styles.Body_left_Picture} 
              />
            </View>
    
            : null}
    
            <SafeAreaView  style={styles.Body_right} >
                <View style={styles.Body_Container} >
                  <Image 
                    source={require("../assets/PlaceHolderLogo.png")} 
                    style={styles.Logo} 
                  />
                  <Text h1 style={styles.Login_Title}>Let's Sign In</Text>
                  <Text style={styles.Login_Title_Child}>Welcome Back!</Text>
    
                  <View style={styles.Input_Group} >
                    <TextInput value={userName} placeholder={'Enter Username'} placeholderTextColor="#fff" onChangeText={(inputOne) => setUserName(inputOne)} style={styles.Input} />
                    <TextInput value={userPassword} placeholder={'Enter Password'} placeholderTextColor="#fff" onChangeText={(inputTwo) => setUserPassword(inputTwo)} style={styles.Input} />
    
                    <Pressable style={styles.Btn_Main} onPress={() => navigation.navigate("Profile", {Username: userName})}>
                      <Text style={styles.Btn_Text}>Sign In</Text>
                    </Pressable>
                  </View>
    
                </View>
            </SafeAreaView >
    
          </View>
        );
    }
    
    export default Login;

Profile.js

export default function App({route}) {

  const Profile_Username = route.params ? route.params.Username : "UnKnown"

  const Profile_Picture = "https://www.trickscity.com/wp-content/uploads/2019/02/pubg-dp.jpeg"

  return (
      <View style={{ position: 'relative', backgroundColor: "#242629", flex: 1 }} >
        
        <View style={{ position: 'relative', backgroundColor: "#242629", flex: 0.3 }} ></View>


        

        <View style={{ position: 'relative', backgroundColor: "#16161a", flex: 1 }} >

          <View style={styles.ProfileParent} >

            <View style={styles.ProfilePictureParent}>
              <Image 
                source={{uri: Profile_Picture}} 
                style={styles.ProfilePicture} 
              />
            </View>

            <View style={styles.ProfileTitleBox}>
              <Text style={styles.ProfileName}>{Profile_Username}</Text>
              <Text style={styles.ProfileTag}>Member</Text>
            </View>

          </View>

        </View>


      </View>
      
  );
}

---[ PWA Files ]---

serve.json

{
  "headers": [
    {
      "source": "static/**/*.js",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ]
}

manifest.json

{
  "background_color": "#ffffff",
  "display": "standalone",
  "lang": "en",
  "name": "DevBuild",
  "short_name": "DevBuild",
  "start_url": "/?utm_source=web_app_manifest",
  "orientation": "portrait",
  "icons": [
    {
      "src": "\\pwa\\chrome-icon\\chrome-icon-144.png",
      "sizes": "144x144",
      "type": "image/png"
    },
    {
      "src": "\\pwa\\chrome-icon\\chrome-icon-192.png",
      "sizes": "192x192",
      "type": "image/png"
    },
    {
      "src": "\\pwa\\chrome-icon\\chrome-icon-512.png",
      "sizes": "512x512",
      "type": "image/png"
    }
  ]
}

CodePudding user response:

Solution

Thanks to @pfndesign

Told me to edit the serve.json to include

  "rewrites": [
    { "source": "/**", "destination": "/index.html"}
  ]

Note I am not 100% sure on what it does but it worked for me,

pfndesign also linked me to this: https://github.com/vercel/serve-handler#options

Hope this helps anyone reading this :D

CodePudding user response:

your problem is not the expo or react-native, you need to use htaccess in your host to send all of your requests to index.html where your PWA is . the first time you are navigating to your PWA it will load the index.html and each route is loaded within that HTML file with the URL address bar changing according to your linking config but when you refresh the page host think that it has to go to subfolders because it has no idea that your routes don't exist outside of your PWA

simply create a .htaccess file inside of your PWA folder and add this code to it, it should solve your problem

<IfModule mod_rewrite.c>
  RewriteEngine On  
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
  RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
  RewriteRule ^ - [L]
  RewriteRule ^ /index.html [L]
</IfModule>

for your local environment edit serve.json and add code bellow

"rewrites": [
    { "source": "/**", "destination": "/index.html" }
]

for more info about rewrites, you can check https://github.com/vercel/serve-handler#options

  • Related