Skip to main content

Customize the client

Now that we have both a client and a backend, we can start to build a project with Squid! Developing with Squid allows us to easily use a database to insert, read, update, and delete data from the client-side without worrying about setting up an API.
At this point, we can begin to perform CRUD operations in our database straight from our client side code.

The Project

This guide explains how to create a simple React application that utilizes the Squid React SDK with a Squid backend. The application inserts random users into the database and displays their information on a React website.

Insert

Squid organizes data into collections and documents. Documents are individual records in the database (such as rows in a table), while collections are groups of documents (similar to unstructured tables). To get a reference to a collection in React, use the useCollection hook. Squid's built-in database will automatically create a new collection for this collection reference:

Client code
const userCollection = useCollection<User>('users');

To insert into the new collection, create a new document and insert data into the new document:

Client code
userCollection.doc(userId).insert({
id: userId,
email: email,
age: Math.ceil(Math.random() * 100),
});

A full insert example is below. For now, we will set the email attribute to be the user’s id@email.com. Create a new components directory with a createUser.tsx file. In src/components/createUser.tsx:

Client code
import { useCollection } from '@squidcloud/react';

// Define your type
type User = { id: string; email: string; age: number };

export default function CreateUser() {
const userCollection = useCollection<User>('users');
const insert = () => {
const userId = crypto.randomUUID();
const email = `${userId}@email.com`;
userCollection.doc(userId).insert({
id: userId,
email,
age: Math.ceil(Math.random() * 100),
});
};
return (
<>
<button onClick={insert}>Insert new user</button>
</>
);
}

Read

To get the users collection reference from Squid, you first bring in the collection using the useCollection hook:

Client code
const collection = useCollection<User>('users');

You can now get the list of users, which will be streamed to the client and kept up-to-date in real-time:

Client code
const users = useQuery(collection.query());

Each user in the users array has a data object. For more querying options see the documentation. Below is a full read example in src/components/readUsers.tsx:

Client code
import { useCollection, useQuery } from '@squidcloud/react';

type User = { id: string; email: string; age: number };

export default function ReadUsers() {
const collection = useCollection<User>('users');
/** The list of users will be streamed to the client and kept up-to-date */
const users = useQuery(collection.query());

return (
<ul style={{ listStyle: 'none', paddingLeft: '0px' }}>
{users.data.map((user) => (
<li key={user.data.id}>
{user.data.email} - {user.data.age}
</li>
))}
</ul>
);
}

At this point, we can update our src/App.tsx and test the app:

Client code
import './App.css';
import CreateUser from './components/createUser';
import ReadUsers from './components/readUsers';
function App() {
return (
<>
<CreateUser />
<ReadUsers />
</>
);
}
export default App;

With Squid's real-time functionality, you can insert data in one tab and instantly see the updates in other tabs without requiring any additional code!

Update

To update a document in the collection, call the update() method on a DocumentReference and pass in an object that contains the partial update data as an argument. To do so, we will create a simple HTML form which can update a user’s age:

Client code
<form onSubmit={onSubmit}>
<label htmlFor="email">Email: </label>
<input id="email" />
<label>Age: </label>
<input id="age" type="number" />
<input type="submit" value="Update age" />
</form>

We will update the first user with the matching email field specified in the form. In src/components/updateUser.tsx:

Client code
import React from 'react';
import { useCollection, useQuery } from '@squidcloud/react';

type User = { id: string; email: string; age: number };
type EventObj = { value: string }; // Used for form event data access

export default function UpdateUser() {
const collection = useCollection<User>('users');
const users = useQuery(collection.query());

const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
// Find the first user with the matching email
const user = users.data.find(
(user) =>
user.data.email == (e.target as unknown as Array<EventObj>)[0].value
);

if (user) {
user
.update({
age: Number((e.target as unknown as Array<EventObj>)[1].value),
})
.then(() => console.log('User updated successfully'))
.catch((error) => console.error('Failed to update user', error));
}
};

return (
<form onSubmit={onSubmit} style={{ padding: '20px' }}>
<label htmlFor="email">Email: </label>
<input id="email" />
<label style={{ marginLeft: '10px' }}>Age: </label>
<input id="age" type="number" />
<input type="submit" value="Update age" />
</form>
);
}

Next we can import our new update component into src/App.tsx and test our new ability to update a user’s age.

Delete

To delete a document, you can call the delete() method on a DocumentReference. Create a new deleteUser.tsx file where we will create the new component. The component will delete the first user that matches with the specified email field. In src/components/deleteUser.tsx:

Client code
import React from 'react';
import { useCollection, useQuery } from '@squidcloud/react';

type User = { id: string; email: string; age: number };
type EventObj = { value: string }; // Used for form event data access

export default function DeleteUser() {
const collection = useCollection<User>('users');
const users = useQuery(collection.query());

const onSubmit = (e: React.FormEvent) => {
e.preventDefault();
const user = users.data.find(
(user) =>
user.data.email == (e.target as unknown as Array<EventObj>)[0].value
);

if (user) {
const id = user.data.id;
user
.delete()
.then(() => console.log(`User ${id} deleted`))
.catch((error) => console.error('Failed to delete user', error));
}
};

return (
<form onSubmit={onSubmit}>
<label htmlFor="email">Email: </label>
<input id="email" />
<input type="submit" value="Delete user" />
</form>
);
}

After completing the delete component, import it into src/App.tsx. We are now able to use Squid’s built in database service to accomplish all the major functionality that is required in a database.

Next steps

Congratulations on completing the tutorial! To learn about key features of the Squid backend including security functionality, view the Backend SDK documentation. To learn about the functionality of the Squid Client SDK including more complex data queries, managing secrets, and interacting with your storage buckets, view the Client SDK documentation.