React vs React + Redux vs React+GraphQL : Perspective from Front end Development
Introduction:
In this blog post, I am trying to explain the comparison between React vs React+Redux vs React+GraphQL with respect to application’s state management.
React Application:
It is not necessary to implement state management library like ‘Redux’ in all the react apps. We can manage the state changes in parent/root component itself. Parent components have to send state object as props to the child components in order for them to access the state. Keep in mind that we should pass mutation function reference down to the child components as well. Any changes in the state can be done in the nearest containers.
Passing state to the child components:
<TodoList deleteClicked={this.removeTodo} todos={this.state.todos} changeClicked={this.changeTodo}>
</TodoList>As you can see, todos list is passed to its child component TodoList as props to render it.
TodoList component can access the data like below from props.
let pendingList = this.props.todos.filter(todo => todo.completed === false);You can check the source code here of a simple TODO application..
Note : I have created all the components as stateful components just to showcase the use cases in the above demo project. Best practise is to create stateless components as much as possible.
This method will work for smaller application like the one referred above. Imagine if we have 5 or 6 child components, we might end up having a very huge parent/root component with lots of methods and properties. If least child component wants to access some state property, it has to be passed along all the child components to reach the lower level component ,which creates overhead. Passing down state props and lot of callbacks will make the code ugly and very difficult to maintain. To overcome all the above disadvantages, they have introduced redux library for application state management.
Disadvantages:
- With more child components and complex UI, it will become very difficult and messy to manage state in the parent component.
- Any change in the state re-renders all child components inside parent component which impacts performance.
- Reuse of components will be difficult as child components props are tightly coupled with parent component.
- Data flow would be difficult if more components shares the same data.
- Very difficult to track the application state while debugging.
React with Redux:
Redux is a state management library for JavaScript applications. Redux is used to store the entire application’s state in the single location. Child components can access the state from this single store and need not pass around the state from parent to child.
Redux gives us the clear separation of application state (not the component’s local state ) and its presentation layer. In the redux pattern, any component can change the state and all the components which are interested in that particular state object will get notified. This can be achieved through dispatch, actions and reducers. Below image explains how the redux works.

In our demo example, append the TodoList component like below
<div className="home">
<div className="title shadow-sm p-3 mb-5 bg-white rounded">TODOAPP</div>
<AddTodo />
<TodoList />
</div>No need to pass around any props or mutations function references. Child components get the state from the global store.
const _TodoList = connect(state => ({ todoList: [...state.todoList.todoList] }),dispatch => bindActionCreators({ ...Actions }, dispatch),)(TodoList);Our child component is wrapped with redux store provider now. By using redux, we can share the application state among components and the code now is very easy to maintain. More the components, more the code complexity, redux will reduce this complexity by separating the application state. We can track the state of the application at any point while debugging.
The only downside is that even for small applications, more lines of code has to be added for it to work. In the example referred, for adding a small feature to the application, we have to edit three files such as reducers, actions and components.
Check the redux implementation here.
React with GraphQL :
GraphQL clients used to send and receive the GraphQL queries and response from GraphQL server. In this article, I am using react-apollo as GraphQL client. Apollo client is very useful in managing the data between our server and client.
Using the react-apollo we can get rid of huge chunk of codes we have written for redux to manage application state. Apollo clients have released special components for Queries, Mutations and Subscriptions. Apollo-client has made the life of a developer easy by releasing Higher order components without which a developers without which developer has to create high order components to wrap our custom components to work with queries and mutations. Wherever we want to use query or mutation , we can simply wrap our component with these apollo’s HOCs.
Apollo uses built in cache mechanism to sync application state for all UI components. The same TODO app is done with react and react-apollo. You can very well compare the code with redux implementation for better understanding of how react-apollo useful in reducing the lines of code.
Query Component:
To query the list of todos, we just have to wrap our JSX with Query HOC of apollo’s like shown below:
<Query
query={gql`
query {
allTodos{
id ,todoItem ,completed
}
}
`}>
{({ loading, error, data }) => {
if (loading) return <p>Loading...</p>;
if (error) return <p>Error :(</p>;
return (
<div className="completed-list">
<div className="todo-pending">
{data.allTodos.filter(todo => todo.completed === false).map(function (todo, index) {return
(<div className="todo-item row shadow-sm p-3 mb-5 bg-white rounded" key={index}>
<span className="todo-item-label"> {todo.todoItem} </span>
</div>);
}, this)}
</div>
</Query>The code above list all the todos. As you can see error state and loading is also taken care by the apollo-client itself which makes the developer life easy. If you want to show some other component based on error or loading, you can make use of these props. The queries can be used inside the component itself which is very useful in maintaining the code. For re-usability, the queries can be kept in separate file and can be imported wherever is required as I had did in the demo application.
In the redux way, how we do this is, create a store and create a state for the todos and store the server response in the todos state. In redux, we have to restructure the data based on the UI representation. Using the redux connect , components can get the state from store. Any other components needs to show the same data, can get it from store.
In Apollo-client, when application queries for specific data, it fetches it from server and normalises it and stores it in the cache. Apollo-cache stores the data as Objects instead of plain JSON strings. Any other component querying for the same data will get it from cache through which server request round trip is reduced and the data across all the components is in sync. And moreover, in Apollo-client we don’t need to restructure the data, as we can mention the structure while requesting for data.
Mutation Component:
Similar to Query component, Mutation component is used to wrap the component/element in which you want to call mutate function. Below is the example of mutate function:

As you can see, addTodo is the mutation in the server, which will get called on button click. If you refer the code, clicking the button “new todo” will add the new todo in the todos list in server, but that change will not reflect in the UI, as the UI state is from internal cache. Whenever there is change in the data, we have to update the apollo cache as well using writequery built in function provided by Mutation component. Now the server and client data is in sync and any component using the todos list will get updated.

If user changes the todo state to completed state, mutation doesn’t need to call the update cache method as it is taken care by apollo-client. Make sure you are returning the unique id for that mutation query for this function to work properly.


The state of the application is in sync between the components and as well as the server and client. All of this features are achieved because of awesome apollo-client library with very less lines of code.
Apollo-client cache will be able to manage the server data only. To manage the local data (for eg:data only shared between the components for that instance) redux can be used. Apollo community developers wants to keep Apollo cache as single source of truth, so they introduced apollo-link-state and apollo-link libraries. It will be the entire replacement for redux, as you can manage local data and server data in the cache itself. We can go over in detail about apollo-link-state and apollo-link in my next article.
Subscriptions:
Subscriptions are one of the hot topics in GraphQL, used for real time data communication between server and client. Here we are using web-sockets for the data communications. You can go through the official page on how to set up subscriptions in client side. You can checkout my simple demo video on how subscription and unsubscribe works in react-apollo.
Its very easy to setup subscription model in client application using apollo-react. Imagine how difficult it would be to set up the same, without apollo-react.
Source Code:
You can find the entire source code for all the demo apps in:
Compare the code by yourself and definitely you will become fan of Apollo client.
Conclusion:
Apollo-client gives us lots of easy to use features with less code and very minimal configurations. Query, Mutation and Subscription components came as big advantage in saving the development time.
Try to use apollo-client for react and let me know you experience.
