Redux and Apollo are popular implementations of Flux architecture and GraphQL respectively. A common pattern is to make a GraphQL query with data from the Redux state. If the state value changes, Apollo should re-run the query and the new data should be reflected in the UI.
As an example, let’s consider a restaurant website with a rotating menu populated from the server; when a visitor selects a date, the menu should update.
First, let’s create the dispatcher and pass it to the contained component.
function mapDispatchToProps(dispatch: Dispatch): DispatchProps {
return {
selectDate: (date) => {
dispatch({
type: SELECT_MENU_DATE_ACTION_TYPE,
menuDate: date
});
}
};
}
Update the state with the new menuDate
when the contained component dispatches the action.
export function updateState(state: State, action: MenuAction): State {
switch (action.type) {
case SELECT_MENU_DATE_ACTION_TYPE:
return {
...state,
menuDate: action.menuDate
};
default:
return state;
}
}
Now that the Redux state is updated, we need to use the new menuDate
in our GraphQL query.
function mapStateToProps(state: State): StateProps {
return {
date: state.menuDate
}
}
const connectRedux = connect(mapStateToProps);
Set up the GraphQL query to take in a variable, $date
.
const query = gql`
query Menu($date: String!) {
menu(date: $date) {
items {
name
priceInCents
}
}
}
`;
Map the menuDate
from the Redux state to the $date
GraphQL variable.
function mapOwnPropsToOptions(ownProps: ApolloOwnProps) {
return {
variables: {
date: ownProps.date.toISOString()
}
};
}
Then connect the query with the map from the query result to the contained component’s props, MenuProps
.
function mapQueryResultToContainedProps(opts: OptionProps<ApolloOwnProps, ApolloQueryResult>): MenuProps {
if (!opts.data || opts.data.loading || !opts.data.menu) {
return {
items: []
};
}
return {
items: opts.data.menu.items
};
}
const connectApollo = graphql<any, ApolloQueryResult, { date: string }, MenuProps>(
query,
{
options: mapOwnPropsToOptions,
props: mapQueryResultToContainedProps
}
);
Now we can feed the Redux output into Apollo, and then the final output to the contained component.
export const Menu = connectRedux(connectApollo(MenuComponent));
At this point, you should be able to see the Redux state changes triggering Apollo queries as expected. See this GitHub project for the complete code example.