Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does reselect createStructuredSelector work in Typescript?

I’m trying to understand how the reselect method createStructuredSelector works in Typescript. I see this pattern a lot:

export interface SomeProps {
   readonly property1: string;
   readonly property2: boolean;
   readonly property3: number;
}

export interface SomeOwnProps {
   readonly property3: number;
}

export const someSelector = createStructuredSelector<
    SomeState,
    SomeOwnProps,
    SomeProps
>({
   property1: property1Selector,
   property2: property2Selector,
   property3: (_, props) => props.property3
});

I don’t understand the purpose of the types inside of the angle brackets. I think SomeState is the Redux store state, SomeOwnProps are the props that were passed in by the parent component, and SomeProps are all the props that this component uses. But what is the difference between SomeOwnProps and SomeProps, and why do you need both? How come you can’t just use SomeProps since it also contains the properties defined in SomeOwnProps? Thanks!

like image 983
d0nutz1 Avatar asked Dec 28 '18 19:12

d0nutz1


1 Answers

createStructuredSelector comes in two variants — one takes your component's own props, the second doesn't. If your desired selection does not depend on props, it's easier to go with the latter.

Consider this slightly contrived example:

/**
 * Data source (Redux store or a single reducer).
 */
interface State {
  readonly property1: string;
  readonly property2: boolean;
  readonly property3: number;
}

/**
 * Your component's OwnProps.
 */
interface OwnProps {
  index: 1 | 2 | 3;
}

/**
 * The interface you want to create.
 */
interface DesiredSelection {
  someString: string;
  someNumber: number;
};

When your selection does not depend on props:

const mySelector = createStructuredSelector<State, DesiredSelection>({
  someString: state => state.property1,
  someNumber: state => state.property3
});

When your selection does depend on props:

const mySelectorBasedOnProps = createStructuredSelector<State, OwnProps, DesiredSelection>({
  someString: state => state.property1,
  someNumber: (state, props) =>
    (props.index === 1)
      ? 1
      : state.property3
});

The distinction between OwnProps and DesiredSelection is needed because the former can influence the latter. It's a common pattern to select data from different parts of your Redux store based on the props your component has received from its parent.

Somewhat more realistic example:

interface State {
  translations: {
    au: 'Hello, mate!',
    uk: 'Welcome, old chap!'
  }
}

interface OwnProps {
  country: 'au' | 'uk';
}

interface ConnectedProps {
  message: string
};

/**
 * These are all props your component will receive.
 */
type Props = OwnProps & ConnectedProps;

const getMessage = createStructuredSelector<State, OwnProps, ConnectedProps>({
  message: (state, props) => state.translations[props.country]
});
like image 85
Karol Majewski Avatar answered Nov 20 '22 09:11

Karol Majewski