
Published August 16, 2018
Simplify Multi-Source Data Flows with Iguazu
Open-Source Redux REST GraphQL React SSR
We are excited to share Iguazu as an open-source project for simplifying data flows from many different sources (i.e., GraphQL, REST, RPC) in Redux applications. Redux provides predictable state transitions with the flux pattern; Iguazu is a pattern for populating that state with asynchronous data. Iguazu and the API adapters we are open-sourcing were created by our frameworks engineering team to address data-loading needs in our large React applications, and we anticipate it can help other teams as well.
Motivation
Larger applications typically need to consume many API types; for example, GraphQL and REST together. The separation of REST, GraphQL and other data into different stores imposed by other libraries that we studied would have added complexity that we didn’t think was required.
Iguazu allows us to have a single data store (Redux); enable controlled server-side rendering (SSR) depth; use data from various API types and styles; coordinate that data; and provide common information about the state of that data in a simple interface.
Data flows like a waterfall
If a React component relies on asynchronous data, it typically has to do four things:
- Define a load action responsible for fetching the asynchronous data.
dispatch()
the load action when the component mounts and when the component receives new props (these can change the data the component needs).- Define a
mapStateToProps
function, and use selectors to retrieve the data from the Redux state. - Determine whether the state is actually loaded based on the props the selectors return.
Iguazu seeks to simplify this flow into one step. Instead of using
React Redux’s connect
higher-order component (HOC) looking for a
mapStateToProps
function, Iguazu defines a connectAsync
HOC that makes use of a
loadDataAsProps
function.
Note that as both
connect
andconnectAsync
are HOCs, using one does not preclude use of the other.
import React from 'react';
import { connectAsync } from 'iguazu';
import DataDisplay from './DataDisplay';
function MyContainer({ isLoading, loadedWithErrors, myData, myOtherData }) {
if (isLoading()) {
return <div>Loading…</div>;
}
if (loadedWithErrors()) {
return <div>Oh no! Something went wrong</div>;
}
return (
<React.Fragment>
<DataDisplay data={myData} />
<DataDisplay data={myOtherData} />
</React.Fragment>
);
}
function queryMyData(param) {
return (dispatch, getState) => {
// there are API adapters later below that manage this boilerplate
// this is a simplified example of what they're doing under the hood
const { data, error } = getState().getIn(['path', 'to', 'myData', param]);
const status = data || error ? 'complete' : 'loading';
let promise;
if (data) {
promise = Promise.resolve(data);
} else if (error) {
promise = Promise.reject(error);
} else {
promise = dispatch(fetchMyData(param));
}
return { data, error, status, promise };
};
}
function queryMyOtherData(param) { /* Essentially the same as queryMyData */ }
function loadDataAsProps({ store, ownProps }) {
const { dispatch, getState } = store;
return {
myData: () => dispatch(queryMyData(ownProps.someParam)),
myOtherData: () => dispatch(queryMyOtherData(getState().someOtherParam)),
};
}
export default connectAsync({ loadDataAsProps })(MyContainer);
This pattern lends itself well as a common interface for multiple data sources, like REST, “REST,” REST-like, RPC, GraphQL and other APIs. This can be beneficial in larger applications that usually need multiple API types. We are also releasing the iguazu-rest and iguazu-graphql adapters as open source. An RPC adapter is coming soon.
Here is an example with iguazu-graphql.
import { queryGraphQLData } from 'iguazu-graphql';
function loadDataAsProps({ store: { dispatch }, ownProps }) {
// schema endpoints are configured elsewhere, allowing decoupled reuse
const endpointName = 'example-endpoint';
const query = `
query ($someParam: String) {
path(someParam: $someParam) {
to {
data
}
}
}
`;
const variables = { someParam: ownProps.someParam };
return {
myData: () => dispatch(queryGraphQLData({ endpointName, query, variables })),
};
}
The definition of suspense is …
React’s new Suspense API is coming, and we think Iguazu is well-positioned for that shift. You might
have noticed that the interface of the actions ({ status, promise, data, error }
) is very similar
to React’s
example cache implementation.
While Iguazu and simple-cache-provider were
developed independently, they will be able to speak together very easily.
Community
We’ve benefitted from Iguazu, and we’re excited to see how Iguazu can help your applications too. There are many other features to Iguazu that we have found useful but haven’t discussed here. Check out the Iguazu repo for details!
About the Author
