0% found this document useful (0 votes)
7 views30 pages

React Tutorial_ Beginner to Advanced

The document is a comprehensive tutorial on React, covering its core concepts such as components, JSX, props, state, and hooks, as well as advanced topics like context, error boundaries, and portals. It provides step-by-step instructions on setting up a development environment and creating React applications, along with code examples for various functionalities. The tutorial emphasizes the importance of React's component-based architecture and its growing demand in the job market.

Uploaded by

Vishal Rokkam
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
7 views30 pages

React Tutorial_ Beginner to Advanced

The document is a comprehensive tutorial on React, covering its core concepts such as components, JSX, props, state, and hooks, as well as advanced topics like context, error boundaries, and portals. It provides step-by-step instructions on setting up a development environment and creating React applications, along with code examples for various functionalities. The tutorial emphasizes the importance of React's component-based architecture and its growing demand in the job market.

Uploaded by

Vishal Rokkam
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 30

React Tutorial: Beginner to Advanced

Introduction to React
React is a popular JavaScript library for building user interfaces, particularly for
single-page applications. It was developed by Facebook and is known for its
component-based approach, virtual DOM, and declarative style.

What is React?
● Component-Based: Build UIs by breaking them into reusable components.
● Virtual DOM: Efficiently updates the actual DOM, improving performance.
● Declarative: You describe what the UI should look like, and React handles the
rendering.
Why Learn React?
● Popularity: Large community and extensive ecosystem.
● Performance: Optimized for speed.
● Reusability: Components can be reused throughout the application.
● Flexibility: Can be used for web and mobile development (React Native).
● Job Market: High demand for React developers.

Setting Up Your Development Environment


1. Node.js and npm
React requires Node.js and npm (Node Package Manager). Download and install them
from:
● Node.js: [https://nodejs.org/](https://nodejs.org/)
Verify the installation by running these commands in your terminal:

node -v
npm -v

2. Create a React App


Use Create React App, a toolchain for setting up a modern React development
environment:

npx create-react-app my-react-app


cd my-react-app
npm start

This will:
● Create a new folder called my-react-app.
● Set up the basic React project structure.
● Start a development server.

Open your browser and navigate to http://localhost:3000 to see your React app.

Core Concepts
1. Components
Components are the building blocks of a React application. They are reusable pieces
of UI that can be composed to create complex interfaces.

Function Components
import React from 'react';

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

● A function that returns JSX.


● Takes props (properties) as an argument.

Class Components
import React, { Component } from 'react';

class Welcome extends Component {


render() {
return <h1>Hello, {this.props.name}</h1>;
}
}

● A class that extends React.Component.


● Has a render() method that returns JSX.
● Also takes props.
2. JSX
JSX (JavaScript XML) is a syntax extension that allows you to write HTML-like code in
your JavaScript files.

const element = <h1>Hello, JSX!</h1>;

● Looks like HTML, but it's transformed into JavaScript function calls.
● Allows you to embed JavaScript expressions using curly braces {}.

const name = 'John';


const element = <h1>Hello, {name}!</h1>; // Embedding a variable

3. Props
Props (properties) are used to pass data from a parent component to a child
component.

function Welcome(props) {
return <h1>Hello, {props.name}</h1>;
}

function App() {
return (
<div>
<Welcome name="John" />
<Welcome name="Jane" />
</div>
);
}

● Props are read-only from the perspective of the child component.


● You can pass any type of data as props (strings, numbers, objects, functions,
etc.).
4. State
State is used to store data that a component needs to render and update. Unlike
props, a component can modify its own state.
Using State with Class Components
import React, { Component } from 'react';

class Counter extends Component {


constructor(props) {
super(props);
this.state = { count: 0 };
}

increment = () => {
this.setState({ count: this.state.count + 1 });
};

render() {
return (
<div>
<h1>Count: {this.state.count}</h1>
<button onClick={this.increment}>Increment</button>
</div>
);
}
}

● Initialize state in the constructor.


● Use this.setState() to update the state. Never modify this.state directly.
setState() schedules an update to the component.
Using State with Function Components (Hooks)
import React, { useState } from 'react';

function Counter() {
const [count, setCount] = useState(0);

const increment = () => {


setCount(count + 1);
};
return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
</div>
);
}

● useState is a Hook that lets you add state to function components.


● It returns an array with the current state value and a function to update it.

5. Hooks
Hooks are functions that let you "hook into" React state and lifecycle features from
function components. They were introduced in React 16.8.

Common Hooks
● useState: For adding state to function components (as seen above).
● useEffect: For performing side effects (data fetching, subscriptions, DOM
manipulation).
● useContext: For consuming values from a context.
● useReducer: For more complex state management.

useEffect
The useEffect Hook lets you perform side effects in function components.

import React, { useState, useEffect } from 'react';

function Example() {
const [count, setCount] = useState(0);

// Similar to componentDidMount and componentDidUpdate:


useEffect(() => {
// Update the document title
document.title = `You clicked ${count} times`;
// This function runs after every render
}, [count]); // Only re-run the effect if count changes

return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

● The callback function inside useEffect runs after the component renders.
● The optional second argument (the array [count]) is an array of dependencies. If
the values in the array don't change between renders, the effect won't re-run. An
empty array [] means the effect runs only once on mount and unmount. If you
omit the second argument, the effect runs after every render.
6. Conditional Rendering
Conditional rendering allows you to render different elements or components based
on certain conditions.

Using if statements
function Greeting(props) {
if (props.isLoggedIn) {
return <h1>Welcome back!</h1>;
}
return <h1>Please sign up.</h1>;
}

function App() {
return (
<div>
<Greeting isLoggedIn={true} />
<Greeting isLoggedIn={false} />
</div>
);
}

Using the ternary operator


function Greeting(props) {
return (
<div>
{props.isLoggedIn ? <h1>Welcome back!</h1> : <h1>Please sign up.</h1>}
</div>
);
}

Using logical AND (&&)


function Message(props) {
const { unreadMessages } = props;
return (
<div>
{unreadMessages.length > 0 && (
<h1>You have {unreadMessages.length} unread messages.</h1>
)}
</div>
);
}

7. Lists and Keys


In React, when you render a list of items, you need to provide a unique key prop to
each item. This helps React identify which items have changed, been added, or been
removed, allowing for efficient updates.

function NumberList(props) {
const numbers = props.numbers;
const listItems = numbers.map((number) =>
<li key={number.toString()}>
{number}
</li>
);
return (
<ul>{listItems}</ul>
);
}
const numbers = [1, 2, 3, 4, 5];

● The key should be a stable identifier for each item, such as an ID from a
database.
● Avoid using the array index as the key if the order of items may change.

8. Forms
React handles forms differently than traditional HTML. Form data is typically managed
using state.

Controlled Components
In a controlled component, the form elements' values are controlled by React state.

import React, { useState } from 'react';

function MyForm() {
const [name, setName] = useState('');
const [email, setEmail] = useState('');

const handleSubmit = (event) => {


event.preventDefault();
console.log(`Name: ${name}, Email: ${email}`);
// You would typically send the data to a server here
};

return (
<form onSubmit={handleSubmit}>
<label>
Name:
<input
type="text"
value={name}
onChange={(e) => setName(e.target.value)}
/>
</label>
<br />
<label>
Email:
<input
type="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
/>
</label>
<br />
<button type="submit">Submit</button>
</form>
);
}

● The value attribute of the input elements is bound to the component's state.
● The onChange handler updates the state when the input value changes.

9. Lifting State Up
When several components need to share the same data, you lift the state up to their
closest common ancestor.

import React, { useState } from 'react';

function Child1({ value, onChange }) {


return (
<div>
Child 1:
<input value={value} onChange={onChange} />
</div>
);
}

function Child2({ value }) {


return (
<div>
Child 2: Value from Parent: {value}
</div>
);
}

function Parent() {
const [value, setValue] = useState('');

const handleChange = (event) => {


setValue(event.target.value);
};

return (
<div>
<Child1 value={value} onChange={handleChange} />
<Child2 value={value} />
</div>
);
}

● The value state is in the Parent component.


● The Parent passes the value and the onChange handler to Child1.
● Child2 receives the value as a prop.

Advanced Concepts
1. Context
Context provides a way to pass data through the component tree without having to
pass props down manually at every level.

Creating a Context
import React, { createContext, useContext, useState } from 'react';

const MyContext = createContext();

function App() {
const [value, setValue] = useState('Hello, Context!');
return (
<MyContext.Provider value={value}>
<ComponentA />
</MyContext.Provider>
);
}

Consuming a Context
function ComponentC() {
const value = useContext(MyContext);
return <div>Component C: {value}</div>;
}

function ComponentB() {
return <ComponentC/>
}

function ComponentA() {
return <ComponentB/>
}

● createContext() creates a context object.


● Provider component makes the context value available to consuming
components.
● useContext() Hook lets you consume the context value in a function component.

2. Render Props
A render prop is a function prop that a component uses to share code with other
components.

import React, { useState } from 'react';

class Mouse extends React.Component {


constructor(props) {
super(props);
this.state = { x: 0, y: 0 };
}

handleMouseMove = (event) => {


this.setState({
x: event.clientX,
y: event.clientY
});
}

render() {
return (
<div style={{ height: '100vh' }} onMouseMove={this.handleMouseMove}>
{this.props.render(this.state)}
</div>
);
}
}

function MouseTracker() {
return (
<Mouse
render={({ x, y }) => (
<h1>The mouse position is ({x}, {y})</h1>
)}
/>
);
}

● The Mouse component takes a render prop, which is a function.


● The Mouse component calls the render function and passes it the current mouse
coordinates.
● The MouseTracker component provides the render function, which renders the
UI.
3. Higher-Order Components (HOCs)
A higher-order component (HOC) is a function that takes a component and returns a
new component with enhanced capabilities.

import React, { useState } from 'react';

function withLogging(WrappedComponent) {
return function EnhancedComponent(props) {
const [logMessage, setLogMessage] = useState('');
console.log(`Component ${WrappedComponent.name} is rendering`);
return (
<>
<WrappedComponent {...props} setLogMessage={setLogMessage} />
{logMessage && <div>Log: {logMessage}</div>}
</>
);
};
}

function MyComponent(props) {
const {setLogMessage} = props;
return (
<div>
<h1>My Component</h1>
<button onClick={() => setLogMessage("Clicked!")}>Click</button>
</div>
);
}

const LoggedComponent = withLogging(MyComponent);

function App() {
return (
<LoggedComponent />
)
}

● withLogging is the HOC. It takes MyComponent as an argument.


● It returns a new component (EnhancedComponent) that wraps MyComponent
and adds logging functionality.
4. Refs
Refs provide a way to access DOM nodes or React elements created in the render
method.
Using Refs
import React, { useRef, useEffect } from 'react';

function MyInput() {
const inputRef = useRef(null);

useEffect(() => {
inputRef.current.focus(); // Focus the input element on mount
}, []);

return (
<input type="text" ref={inputRef} />
);
}

● useRef() creates a ref object.


● You attach the ref to a DOM element using the ref attribute.
● The current property of the ref object holds a reference to the DOM element.

5. Error Boundaries
Error boundaries are class components that catch JavaScript errors anywhere in their
child component tree, log those errors, and display a fallback UI instead of the
crashed component tree.

import React, { Component } from 'react';

class MyErrorBoundary extends Component {


constructor(props) {
super(props);
this.state = { hasError: false };
}

static getDerivedStateFromError(error) {
// Update state so the next render will show the fallback UI.
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
// You can also log the error to an error reporting service
console.error(error, errorInfo);
}

render() {
if (this.state.hasError) {
// You can render any custom fallback UI
return (
<div>
<h2>Something went wrong.</h2>
<p>Please try again later.</p>
</div>
);
}

return this.props.children;
}
}

function MyComponent() {
throw new Error("Error from MyComponent");
}

function App() {
return (
<MyErrorBoundary>
<MyComponent />
</MyErrorBoundary>
);
}

● Only class components can be error boundaries.


● Use getDerivedStateFromError to update the state when an error occurs.
● Use componentDidCatch to log the error.
● Wrap any components that might throw errors with an error boundary.

6. Fragments
Fragments let you group a list of children without adding an extra node to the DOM.

import React from 'react';

function MyComponent() {
return (
<>
<h1>Hello</h1>
<p>World</p>
</>
);
}

● <></> is the short syntax for <React.Fragment>.


● Useful for returning multiple elements from a component without adding a
wrapping div.
7. Portals
Portals provide a way to render a child component into a DOM node that exists
outside the DOM hierarchy of the parent component.

import React, { useState } from 'react';


import ReactDOM from 'react-dom';

const modalRoot = document.getElementById('modal-root'); // Assumed to exist in


index.html

function MyModal({ isOpen, onClose, children }) {


if (!isOpen) return null;

return ReactDOM.createPortal(
<div style={{
position: 'fixed',
top: 0,
left: 0,
width: '100%',
height: '100%',
backgroundColor: 'rgba(0,0,0,0.5)',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 1000
}}>
<div style={{
backgroundColor: 'white',
padding: '20px',
borderRadius: '5px',
width: '50%',
maxWidth: '500px'
}}>
{children}
<button onClick={onClose}>Close</button>
</div>
</div>,
modalRoot
);
}

function App() {
const [isModalOpen, setIsModalOpen] = useState(false);

return (
<div>
<button onClick={() => setIsModalOpen(true)}>Open Modal</button>
<MyModal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)}>
<h1>Modal Content</h1>
<p>This content is rendered outside the App component's DOM tree.</p>
</MyModal>
</div>
);
}

● ReactDOM.createPortal() renders the component into a different DOM node


(modalRoot).
● Useful for modals, tooltips, and other elements that need to be positioned
outside of the normal document flow.
8. Memoization
Memoization is a technique for optimizing performance by caching the results of
expensive function calls and returning the cached result when the same inputs occur
again.

React.memo
React.memo is a higher-order component that memoizes function components.

import React, { useState } from 'react';

const MyComponent = React.memo((props) => {


console.log('MyComponent rendered');
return (
<div>
<h1>{props.value}</h1>
</div>
);
});

function App() {
const [count, setCount] = useState(0);
const [otherCount, setOtherCount] = useState(0);

return (
<div>
<MyComponent value={count} />
<button onClick={() => setCount(count + 1)}>Increment Count</button>
<button onClick={() => setOtherCount(otherCount + 1)}>Increment Other
Count</button>
</div>
);
}

● React.memo prevents the component from re-rendering if its props haven't


changed.
● Use it for function components that receive the same props.
● You can provide a comparison function as the second argument to React.memo
for more fine-grained control.
useMemo
The useMemo Hook returns a memoized value.

import React, { useState, useMemo } from 'react';

function App() {
const [a, setA] = useState(1);
const [b, setB] = useState(2);

const result = useMemo(() => {


console.log('Calculating result...');
return a + b;
}, [a, b]);

return (
<div>
<h1>Result: {result}</h1>
<button onClick={() => setA(a + 1)}>Increment A</button>
<button onClick={() => setB(b + 1)}>Increment B</button>
</div>
);
}

● useMemo only recomputes the value when its dependencies ([a, b]) change.
● Useful for expensive calculations or creating stable references.

useCallback
The useCallback Hook returns a memoized callback function.

import React, { useState, useCallback } from 'react';

function App() {
const [count, setCount] = useState(0);
const increment = useCallback(() => {
setCount(c => c + 1);
}, []); // The dependency array is empty, so the function never changes.

return (
<div>
<MyComponent onClick={increment} />
<h1>Count: {count}</h1>
</div>
);
}

const MyComponent = React.memo((props) => {


console.log("MyComponent Re-rendered")
return (
<button onClick={props.onClick}>
Increment
</button>
)
})

● useCallback returns the same function instance across renders, unless its
dependencies change.
● Useful for passing callbacks to optimized child components.

9. Web Workers
Web Workers provide a way to run JavaScript code in a background thread, without
blocking the main thread. This can improve the performance of your React
applications by offloading expensive computations or tasks to a separate thread.

Using Web Workers


1. Create a Worker File: Create a separate JavaScript file (e.g., worker.js)
containing the code you want to run in the background.
// worker.js
self.onmessage = (event) => {
const data = event.data;
// Perform a long running task
let result = 0;
for (let i = 0; i < 1000000000; i++){
result += i;
}
self.postMessage({ result, originalData: data });
};

2. Create worker in React component


import React, { useState, useEffect } from 'react';

function App() {
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);

useEffect(() => {
const myWorker = new Worker(new URL('./worker.js', import.meta.url));

myWorker.onmessage = (event) => {


setLoading(false);
setResult(event.data.result);
console.log('Received from Worker:', event.data);
myWorker.terminate(); // Clean up the worker
};

myWorker.onerror = (error) => {


console.error('Worker error:', error);
setLoading(false);
myWorker.terminate();
};

return () => {
// Cleanup logic when the component unmounts or before re-running effect
myWorker.terminate(); // Terminate the worker to prevent memory leaks
};
}, []);

const runWorker = () => {


setLoading(true);
const myWorker = new Worker(new URL('./worker.js', import.meta.url));

myWorker.onmessage = (event) => {


setLoading(false);
setResult(event.data.result);
console.log('Received from Worker:', event.data);
myWorker.terminate(); // Clean up the worker
};

myWorker.onerror = (error) => {


console.error('Worker error:', error);
setLoading(false);
myWorker.terminate();
};

myWorker.postMessage({ message: 'Hello from React!' });


};

return (
<div>
<button onClick={runWorker} disabled={loading}>
{loading ? 'Loading...' : 'Run Worker'}
</button>
{result !== null && <h1>Result: {result}</h1>}
</div>
);
}

export default App;

○ Create a new worker using new Worker('./worker.js'). The import.meta.url is


crucial to correctly resolve the worker file path.
○ Use worker.postMessage() to send data to the worker.
○ Use worker.onmessage to receive data from the worker.
○ Terminate the worker when it's no longer needed using worker.terminate().
This is very important to prevent memory leaks. Clean up in a useEffect
hook's cleanup function.
10. Testing
Testing is crucial for ensuring the quality and reliability of your React applications.

Types of Tests
● Unit Tests: Test individual components in isolation.
● Integration Tests: Test how components interact with each other.
● End-to-End (E2E) Tests: Test the application as a whole, simulating user
behavior.
Tools
● Jest: A popular JavaScript testing framework (often used with React).
● React Testing Library: A library for testing React components that focuses on
testing from the user's perspective.
● Cypress: A tool for E2E testing.
● Selenium/WebDriver: Another tool for E2E testing.

Example (Jest and React Testing Library)


1. Install Dependencies:
npm install --save-dev @testing-library/react jest

2. Create a Component:
// src/components/Counter.js
import React, { useState } from 'react';

function Counter() {
const [count, setCount] = useState(0);

const increment = () => {


setCount(count + 1);
};

return (
<div>
<h1>Count: {count}</h1>
<button onClick={increment}>Increment</button>
</div>
);
}
export default Counter;

3. Create a Test File:


// src/components/Counter.test.js
import React from 'react';
import { render, fireEvent } from '@testing-library/react';
import Counter from './Counter';

test('increments count when the button is clicked', () => {


const { getByText } = render(<Counter />);
const button = getByText('Increment');
const countDisplay = getByText('Count: 0');

fireEvent.click(button);

expect(countDisplay).toHaveTextContent('Count: 1');
});

4. Add test script to package.json:


"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test", // Add this line
"eject": "react-scripts eject"
},

5. Run the test:


npm test

This will run the test and output the result.


11. Routing
Routing is the process of navigating between different views or pages in a single-
page application. React itself doesn't provide routing; you need a third-party library.

React Router
React Router is the most popular routing library for React.
1. Install React Router:
npm install react-router-dom

2. Set up Routing:
import React from 'react';
import { BrowserRouter as Router, Routes, Route, Link } from 'react-router-dom';

function Home() {
return <h2>Home Page</h2>;
}

function About() {
return <h2>About Page</h2>;
}

function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
</ul>
</nav>

<Routes>
<Route path="/" element={<Home />} />
<Route path="/about" element={<About />} />
</Routes>
</div>
</Router>
);
}
● BrowserRouter enables client-side routing.
● Routes and Route define the mapping between URLs and components.
● Link is used for navigation. It prevents a full page reload.
● useParams hook can be used to access route parameters.

12. Redux
Redux is a state management library for JavaScript applications. It provides a
centralized store for managing the state of your application, making it easier to
reason about and debug.

Core Concepts
● Store: Holds the application's state.
● Actions: Plain JavaScript objects that describe an event that occurred.
● Reducers: Functions that specify how the application's state changes in
response to actions.
● Dispatch: A function used to send actions to the store.
● Selectors: Functions that extract specific pieces of data from the store.
Example
1. Install Redux and React Redux:
npm install redux react-redux

2. Define Actions:
// src/actions/counterActions.js
export const INCREMENT = 'INCREMENT';
export const DECREMENT = 'DECREMENT';

export const increment = () => ({


type: INCREMENT
});

export const decrement = () => ({


type: DECREMENT
});

3. Define Reducers:
// src/reducers/counterReducer.js
import { INCREMENT, DECREMENT } from '../actions/counterActions';

const initialState = { count: 0 };

function counterReducer(state = initialState, action) {


switch (action.type) {
case INCREMENT:
return { ...state, count: state.count + 1 };
case DECREMENT:
return { ...state, count: state.count - 1 };
default:
return state;
}
}

export default counterReducer;

4. Create the Store:


// src/store.js
import { createStore } from 'redux';
import counterReducer from './reducers/counterReducer';

const store = createStore(counterReducer);

export default store;

5. Connect Redux to React:


import React from 'react';
import { connect } from 'react-redux';
import { increment, decrement } from './actions/counterActions';
import store from './store';
import { Provider } from 'react-redux';

function Counter(props) {
return (
<div>
<h1>Count: {props.count}</h1>
<button onClick={props.increment}>Increment</button>
<button onClick={props.decrement}>Decrement</button>
</div>
);
}

const mapStateToProps = (state) => ({


count: state.count
});

const mapDispatchToProps = {
increment,
decrement
};

const ConnectedCounter = connect(mapStateToProps, mapDispatchToProps)


(Counter);

function App() {
return (
<Provider store={store}>
<ConnectedCounter />
</Provider>
);
}

export default App;

● createStore() creates the Redux store.


● Provider makes the store available to connected components.
● connect() connects a React component to the Redux store.
● mapStateToProps maps state to component props.
● mapDispatchToProps maps action creators to component props.
13. GraphQL
GraphQL is a query language for your API, and a server-side runtime for executing
queries by using a type system you define for your data. It's an alternative to REST.

Key Differences from REST


● Fetching: GraphQL allows you to request only the specific data you need,
avoiding over-fetching or under-fetching. REST typically requires multiple
endpoints.
● Endpoints: GraphQL uses a single endpoint, while REST uses multiple endpoints.
● Schema: GraphQL has a strong type system that defines the structure of your
data.
Example (using Apollo Client)
1. Install Apollo Client and GraphQL:
npm install @apollo/client graphql

2. Set up Apollo Client:


// src/apollo.js
import { ApolloClient, InMemoryCache } from '@apollo/client';

const client = new ApolloClient({


uri: 'https://your-graphql-endpoint.com/graphql', // Replace with your GraphQL
endpoint
cache: new InMemoryCache()
});

export default client;

3. Define a Query:
import { gql } from '@apollo/client';

const GET_CHARACTERS = gql`


query GetCharacters {
characters {
results {
id
name
}
}
}
`;

4. Use the Query in a Component:


import React from 'react';
import { useQuery } from '@apollo/client';
import { GET_CHARACTERS } from './queries';
import client from './apollo';
import { ApolloProvider } from '@apollo/client';

function Characters() {
const { loading, error, data } = useQuery(GET_CHARACTERS, {client: client});

if (loading) return <p>Loading...</p>;


if (error) return <p>Error: {error.message}</p>;

return (
<div>
<h1>Characters</h1>
<ul>
{data.characters.results.map((character) => (
<li key={character.id}>{character.name}</li>
))}
</ul>
</div>
);
}

function App() {
return (
<ApolloProvider client={client}>
<Characters />
</ApolloProvider>
)
}

export default App;

● ApolloClient is used to connect to the GraphQL server.


● gql is used to define GraphQL queries.
● useQuery Hook executes the query and provides the results.
● Wrap your application with ApolloProvider

You might also like