Search code examples
javascriptreact-nativereact-native-webview

react-native-webview Navigate to a list of URLs?


As the question title says, I am trying to navigate to a list of urls using React Natives WebView component. Here is how I am attempting to accomplish this:

export default function App() {
  
  const webViewScript = `
    let urls = ["http://example1.com", "http://example2.com", "http://example3.com"];
    urls.forEach((url) => {
      window.location = url;
      window.ReactNativeWebView.postMessage(document.documentElement.innerHTML);
    });

    true; // note: this is required, or you'll sometimes get silent failures
  `;

  return (
    <WebView
      source={{ uri: navUri }}
      onMessage={(event) => {
        // do something with `event.nativeEvent.data`
        alert(event.nativeEvent.data);
      }}
      injectedJavaScript={webViewScript}
    />
  );
}

However, the foreach loop in the injected javascript does not block, so example3.com is the only url that actually loads. I've considered keeping a counter variable in localStorage and using that to index the array, incrementing after each page load before redirecting to the next URL (since a local variable would lose its state upon page change). But I feel there might be a better way to accomplish what I am trying to achieve, and so I am reaching out to others on SO for your valuable input.


Solution

  • If your goal is to navigate to a list of urls then i think your approach might be complicating it a bit.

    The webview has callback prop ´onLoadEnd´ for when a site has loaded that you can use to trigger the next navigation.

    Also you do not need to store a variable in localStorage, reacts useState is perfect for this.

    Demo

    const urls = [
      'https://github.com/react-native-webview/react-native-webview',
      'https://stackoverflow.com/',
      'https://expo.dev/',
    ];
    
    export default function App() {
      const [activeIndex, setActiveIndex] = useState(0);
    
      return (
        <WebView
          style={styles.container}
          source={{ uri: urls[activeIndex] }}
          onLoadEnd={() => {
            if (activeIndex + 1 === urls.length) return;
            setActiveIndex(activeIndex + 1);
          }}
        />
      );
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        marginTop: Constants.statusBarHeight,
      },
    });