Build a React-based front-end app for your Weaviate neural search
A complete implementation guide to creating a React.js app styled with Material UI that integrates with a Weaviate dataset
Introduction
In this article, we will be using React hooks to build our React app, style it with Material UI and learn how to integrate it with Weaviate neural search. This article will go through the steps of starting a React.js app from scratch, building the UI necessary to interact with Weaviate, and display results in the app’s interface.
But before we get into it, let me give you a brief introduction about what Weaviate is and some of its use cases.
What is Weaviate?
Weaviate is a cloud-native, modular, real-time vector search engine. It is extremely powerful and it makes a lot easier to search through vast amounts of data. Unlike traditional search engines, where you need to search for exact words in order to retrieve the desired data, Weaviate uses vector indexing mechanisms at its core to represent the data. In other words, Weaviate places the data in a vector-space near other text with similar or related meaning. This amazing feature allows you to search for data objects without needing to type exact words. The below image shows an example of a query result for the search phrase “Traveling in Asia”. The results are a list of articles that may not have the exact words ‘Traveling”, “in”, or “Asia” in its title, but Weaviate is able to identify a close relationship between the words and display these results.
There are numerous use cases for when to use Weaviate. Some of the most popular use cases include the following but are not limited to: Semantic search, image search, similarity search, anomaly detection, power recommendation engines, e-commerce search, data classification in ERP systems, automated data harmonization, cybersecurity threat analysis
Check out Weaviate’s documentation for more information.
Setting up Weaviate
There are different ways you can set up Weaviate. In this article, We’re going to use the publicly available endpoint at https://demo.dataset.playground.semi.technology/ which serves a demo dataset including 1000+ news articles to search through. This public endpoint is read-only, but you could also set up your own instance of Weaviate (either locally or in the cloud) and then import your own data. For more resources on how to set up Weaviate, see Weaviate’s documentation.
Creating your React.js app
A quick and efficient way to start a new React.js app, is using the create-react-app toolchain. In case you aren’t too familiar with React.js, I would recommend becoming more familiar with it before proceeding to the next steps. React.js provides a really good starter guide in case you need it.
To create a new React.js app, go to your desired folder in the terminal and run the following command:
Once completed, go to the project root folder:
Once in the root folder, fire up the app:
This will run the app at http://localhost:3000 and keep the hot loading going so it automatically updates the app every time you make changes and saves them. And if by any chance you have something else running on http://localhost:3000, you’ll be prompted to use a different port. Just answer yes if that’s the case.
Cleaning up the React.js app
Create-react-app comes with template files and because we won’t need some of them, we can go ahead and delete them. Inside the src folder, we can delete the following files: App.test.js , logo.svg, reportWebVitals.js, setupTests.js.
Then, still inside the src folder, go to the index.js and delete the following:
And
Still inside the src folder, go to the App.js file and delete the following:
And
Lastly, go to the file App.css and delete the following:
Now we have a greenfield app, which we can use as a starting point for our search frontend. Save the app and you should see an empty page in the browser with no errors.
Creating the UI form to interact with Weaviate
In this app, we will be browsing through Weaviate’s news articles demo dataset. To accomplish this, we will need a text input to type keywords, and a search button to trigger the search function.
To give these elements some style, we will be using Material UI components. If you aren’t too familiar with Material UI, check out their documentation to learn more. It’s easy to get started and extremely powerful.
Go to the app’s root folder and run the following command to install Material-UI:
Also, install Material UI icons package as we will be using it later for the search button icon:
Once both are installed, go to your App.js file and import the TextField component at the top of the file:
Inside the <div> element with the className App, render the TextField element like this:
Now let’s add our search button. To accomplish this, import Material UI’s Button component as well as the SearchIcon to the top of the App.js file:
Below the TextField Component, render the Button component with the SearchIcon:
Add some padding in the App.css file:
And you should get something that looks like this:
Using React hooks to store the input value
Looking good so far. Now it’s time to use React’s state to store the value of the TextField component. We will be using React hooks to accomplish this. First, import the useState hook at the top of the App.js file:
Second, define the state variable. Refer to the useState docs for details:
Next, set keyword to be the value of the TextField component and also the onChange event so it updates the value of keyword as you type:
Hooking up the search Button component
Let’s hook up our Button component with the onClick event to trigger the search function (we can call it weaviateMagic()):
The weaviateMagic function is not defined yet. To define it, let’s create a new file called functions inside the src folder:
Inside this file, we can define our weaviateMagic function and export it using ES6 modules. For now, the function will simply console log ‘it works’ so we can make sure it works properly. Later on we will write the functionality for it.
At the top of the App.js file, import the weaviateMagic function:
To make sure this works, save all the files and go to the browser’s console. When you click on the search Button component, ‘it works’ should be printed.
That’s it! Our form is set up, styled and ready to go.
Introducing Weaviate to our React.js app
Great work so far. Now that our form is ready on the frontend, it’s time to hook it up to Weaviate. All interactions with Weaviate happen through RESTful API and GraphQL requests. To make our lives easier, Weaviate features 3 client packages (Go, Python, and JavaScript) which abstracts away these interactions providing an easier and smoother interaction. We are, of course, going to be using the JavaScript client package since this is a React.js application.
We can install the Weaviate JavaScript client package via npm:
After installation is complete, import the package at the top of the functions.js file:
As explained in the Weaviate JavaScript client docs, we also need to set up a variable for our client and connect it to the news articles dataset we discussed earlier:
Now that the Weaviate JavaScript client is set up, we can go ahead and finish writing our weaviateMagic() function. To accomplish this, we need to introduce Weaviate’s Get{} function. This function is Weaviate’s most direct way of accessing your data. For more details on how this function works check out the Get{} docs.
Notice a few things about this function. We use the Get{} function to access the data. Then we use the withNearText() method to filter the search by our keyword with a certainty of 0.7. Since this is a GraphQL API running — we’ll only get back what we requested, which is this case are the fields title, url, and wordCount. Then we limit our query to 100 results. Finally, we call the do() method to perform the query. Since this is a ES6 promise, we need then() and catch().
Try it out! Type a search phrase and click the search button, then go to the browser’s console, you see the results under Data => Get => Article which should be an array of 100 items. Each item contains the title, wordCount, and url of that particular article.
Saving results in React state
Now let’s save these results in state. Create a new state variable (articles and setArticles) in the App.js file:
And let’s not forget to pass in setArticles to our weaviateMagic() function:
For a better user experience, we can dynamically change the text value of the search button. The value being ‘Searching’ when the function is running and we wait for the results to populate the UI. And ‘Search’ for when we aren’t waiting for results to come through. To achieve this, we can create a new state variable (isSearching and setIsSearching) and set its initial value to false:
Next, we dynamically set the value of the search button. App.js file inside the search button:
We also need to pass in the isSearching and setIsSearching to our weaviateMagic() function. It will be used to change the state of the search button text, letting the user know if the function is running or not.
Finally, to make this work we need to set isSearching to true when the weaviateMagic() function starts running and then set it to false again once the promise resolves:
The final function should look like this:
Displaying the results in the UI
Great work so far! Now that our weaviateMagic function works, it’s time to display the results in the UI of our application. To accomplish this, we will once again leverage the power of Material UI to quickly build something that looks good.
For each article, we will display a Material UI Card component with the fields we requested in the query (title, url and wordCount) inside of it. Let’s first create our Article component which will be rendered for each article in the results array. Create a new file called Article.js inside the src folder:
Inside the Article.js file, import the Card, Typography, and Button components from Material-UI. Also import makeStyles so we can apply custom styling to our Article component.
The Article component has a prop (we can call it article) which contains the data we need. Be sure to also call this prop article later when we pass it from the App.js component. The Article component should look like this:
And above the Article component we can apply custom styles:
Feel free to apply your own styling to the Article component. These are meant to be basic for simplicity sake.
Back to our App.js file, we now need to render the Article component for each array item. Import the Container component from Material-UI and also the Article component:
Underneath the <form> element, render the Container component with a <div> element inside. And then inside the <div> element we need to map through the results array and render an Article component for each item of the array. We can use React’s conditional rendering technique for this:
That’s it! We now have a React.js application that integrates with Weaviate search engine by performing queries to the news articles demo dataset. The results are displayed in the UI.
A results page should look something like this. With 100 cards being displayed:
You can also check out the GitHub repo for this app here. Thanks and happy coding! :)
Conclusion
Weaviate is a powerful tool that can definitely eliminate a lot of headaches when it comes to searching through vast amounts of data. It integrates really well with React.js via the Weaviate client package, which abstracts away GraphQL and RESTful API requests to perform very fast searches with impressive results through a large dataset.
Although this article covered a lot of information, this is only the tip of the iceberg for what Weaviate is capable of. Again, check out Weaviate’s documentation for more details.