Apollo Client. Now with React hooks

The author of the material, the translation of which we publish today, says that the mission of the Apollo Client developers is to make this tool the most modern and convenient solution for managing the state of React applications. The React community is evolving and mastering new and effective ways to develop user interfaces. The creators of Apollo Client strive to ensure that their project supports all the most relevant of the React world. Following this tradition, Apollo Client developers are introducing a new version of the system equipped with React hook support.


Hooks were introduced in React 16.8 . This is a new mechanism that allows you to create stateful components without having to deal with problems specific to class-based components. Now Apollo Client includes three hooks that can be used in applications - in all those places where higher-order components or render props mechanisms are used. These are the useQuery, useMutation and useSubscription . These hooks are easy to learn, they have many advantages over the pre-existing API. In particular, this concerns reducing the size of the application bundle and reducing the amount of boilerplate code.

Beginning of work

If you are going to create a new Apollo project, we recommend installing the following package after you have configured your Apollo Client instance:

 npm install @apollo/react-hooks 

This package exports the ApolloProvider component used to connect the Apollo Client to a React application. In the same way, work was organized using the old API.

If you already have a project that uses Apollo, it means that you have several ways to switch to hooks. The choice of a specific method depends on how exactly you want to make the transition. Details on this can be found here .

Why are hooks the future?

Apollo Client still supports APIs based on higher-order components and render props. These APIs will be present in the system for some time. We believe that in the future, hooks will be the best mechanism for loading data using the Apollo Client. Although those who already use Apollo do not need to switch to hooks right now, they should use hooks for new components. This recommendation has several reasons that we will now consider.

▍When using hooks, you need less code used to work with data

Hooks reduce the amount of boilerplate code used to work with data. This leads to a reduction in the size of the components and to the fact that such components are easier to understand. As a result, developers will no longer need to delve into how higher-order components are arranged, or to analyze the complex logic of render props. To load data, just call the single useQuery function:

 const LAST_LAUNCH = gql`  query lastLaunch {    launch {      id      timestamp    }  } `; export function LastLaunch() {  const { loading, data } = useQuery(LAST_LAUNCH);  return (    <div>      <h1>Last Launch</h1>      {loading ? <p>Loading</p> : <p>Timestamp: {data.launch.timestamp}</p>}    </div>  ); } 

useQuery here is loading data using Apollo Client useQuery hook useQuery
Take a look at this tutorial application where you can see a working example of using Apollo Client hooks.

▍Multiple mutations

When you perform multiple mutations in a single component, using higher-order components or the render props mechanism may lead to code that is hard to understand. The use of the API render prop, the construction of structures consisting of Mutation components embedded in each other, gives a false sense of structured code and its clear hierarchy. The new useMutation hook circumvents this issue completely. The fact is that its use is reduced to a simple function call. The following example shows how several mutations and queries can interact with each other. All this happens within the same component:

 function Message() {  const [saveMessage, { loading }] = useMutation(SAVE_MESSAGE);  const [deleteMessage] = useMutation(DELETE_MESSAGE);  const { data } = useQuery(GET_MESSAGE);  return (    <div>      <p>        {loading          ? 'Loading ...'          : `Message: ${data && data.message ? data.message.content : ''}`}      </p>      <p>        <button onClick={() => saveMessage()}>Save</button>        <button onClick={() => deleteMessage()}>Delete</button>      </p>    </div>  ); } 

The useMutation hook is used useMutation . You can see multiple mutations in action here . This sample application also contains a similar component created using render props. This gives you the opportunity to compare this component with the one created using hooks.

▍ Improved TypeScript support

It's no secret that we are big TypeScript fans. The capabilities of the new hooks go well with the automatic type definitions generated by the Apollo CLI. This greatly facilitates the writing of type-safe code for React components. Here's what loading data using the useQuery and TypeScript hooks looks like:

 import { RocketData, RocketVars } from './types'; const GET_ROCKET_INVENTORY = gql`  query getRocketInventory($year: Int!) {    rocketInventory(year: $year) {      id      year    }  } `; export function RocketInventoryList() {  const { loading, data } = useQuery<RocketData, RocketVars>(    GET_ROCKET_INVENTORY,    { variables: { year: 2019 } }  );  return (/* ... show data ... */); } 

Apollo and TypeScript hooks make it easy to develop strongly typed React components.

Additional Apollo Client enhancements for React developers

Although this release of Apollo focuses on new hooks, we can talk about some more interesting new features.

▍ 50% reduction in bundle size

While the size of the minified and compressed gzip package react-apollo@2 is 10.6 Kb , the size of the react-apollo@3 package is only 7.8 Kb . Moreover, if the @apollo/react-hooks package is enough for you, then the size of the bundle is reduced to only 5.1 Kb . This gives 50% savings compared to react-apollo@2 .

▍ Delayed query execution

The useQuery executes its query at the time the function is called. But just such a behavior of the system is not always necessary. Imagine, for example, a field for entering a search query that gives the user prompts. You may need to display a component with such a field ready to accept what the user enters. But at the same time, the query to the search server will be delayed until the user starts to enter something in the field. To implement this scenario, you can use the useLazyQuery hook, which returns a tuple with the execute function in the second position:

 const [execute, { loading, data }] = useLazyQuery(GET_INVENTORY); 

The request will not be executed until you call the execute function. At this point, the component will be rendered again and the usual query execution scheme implemented using useQuery will be applied.

▍New API documentation

We updated the Apollo Client documentation to add hook information. We recommend them to be used by those who have just started working with our system. However, despite this, we did not remove information from the documentation on how to work with higher-order components and with the render props mechanism. In the code examples that can be found in the documentation, you can now use the new drop-down menu that allows you to switch between code that demonstrates the solution to the same problem using the approach that the reader likes best.

Various code options available in the documentation


The creators of Apollo Client say that they most like React that the main team of developers of this library and the community of enthusiasts around it are constantly striving to improve the usability of React from the point of view of a programmer. The appearance of hooks, which are recommended for everyone to try, is one of the brightest examples of such an aspiration.

We hope that React hooks introduced in Apollo Client will appeal to those who use this project to develop their applications.

Dear readers! Do you use Apollo Client?

Source: https://habr.com/ru/post/463331/

All Articles