Kristofero
Kristofero

Reputation: 41

Deep linking into an already open screen with different params. Is it possible?

I'm working on an app which has a category screen where the relevant posts of the category are displayed. I'm using react-navigation to navigate between the screens and handle the deep linking. The category screen can be accessed in-app or via deep link. To access the category screen via deep link I'm using something like myapp://category/:id.

If the app is already opened and is focused on the category screen the deep link does nothing.

I've currently "fixed" it using the componentDidUpdate life cycle method to compare the ID stored in the state and the ID in navigation.getParam.

componentDidUpdate = () => {
  const { navigation } = this.props;
  const { categoryID } = this.state;
  const paramID = navigation.getParam('id', null);

  if (paramID !== categoryID) {
    this.setState({ categoryID: paramID }, () => {
      // fetch data
    });
  }
}

However, this seems like a dirty fix to me. Is there a better way of doing this? Maybe opening all deep links using push instead of navigate via react-navigation?

Upvotes: 4

Views: 2409

Answers (2)

Giasin
Giasin

Reputation: 1

I employ this method: it takes the array and converts it in a specific manner to yield a distinct identifier for the parameters. Without this process, the functionality wouldn't be correct:

  function generateUniqueID(json) {
    const combinedString = Object.keys(json).sort().map(key => `${key}:${json[key]}`).join(';');
    
    let hash = 0;
    for (let i = 0; i < combinedString.length; i++) {
      const char = combinedString.charCodeAt(i);
      hash = ((hash << 5) - hash) + char;
      hash = hash & hash; // Convert to 32bit integer
    }
    
    return hash.toString();
  }
  const getUserRouteId = ({ params }) => {
    //console.log(generateUniqueID(params));
    return generateUniqueID(params);
  };

Upvotes: 0

Kapobajza
Kapobajza

Reputation: 2459

For anyone who got here wondering how this can be done, like myself, here's the solution:

You can use the getId Stack.Screen property. You just need to return the unique ID from the getId property. Here's an example:

Let's say we have a UserScreen component, which is part of our Stack navigator. The UserScreen has one route param: userId. We can use the getId property like this:

import { createStackNavigator } from '@react-navigation/stack';

const Stack = createStackNavigator();

const AppStack = () => {
  const getUserRouteId = ({ params }) => {
    return params && params.userId;
  };

  return (
    <Stack.Navigator>
      {/* Other routes */}
      <Stack.Screen name="User" component={UserScreen} getId={getUserRouteId} />
    </Stack.Navigator>;
  );
};

Now when you try to normally navigate to this route, using the navigate function, if the param userId in the navigation action is different than on the UserScreen which you're currently on, it will navigate you to a new user screen. React Navigation deep linking uses the navigate function internally.

Upvotes: 8

Related Questions