Giter Site home page Giter Site logo

algolia / recommend Goto Github PK

View Code? Open in Web Editor NEW
29.0 50.0 9.0 12.6 MB

A UI library for Algolia Recommend, available for Vanilla JavaScript and React.

Home Page: https://www.algolia.com/doc/ui-libraries/recommend/introduction/what-is-recommend/

License: MIT License

JavaScript 2.35% TypeScript 97.65%
recommendations algolia react widgets recommend ia javascript

recommend's Introduction

Recommend

Version MIT License

Recommend is the repository packaging the UI components for Algolia Recommend, available for Vanilla JavaScript and React.

Installation

All Recommend packages are available on the npm registry.

yarn add @algolia/recommend-js
# or
npm install @algolia/recommend-js

For React

yarn add @algolia/recommend-react
# or
npm install @algolia/recommend-react

Usage

To get started, you need a container for your recommendations to go in—in this guide, one for Frequently Bought Together, and one for Related Products. If you don't have containers already, you can insert them into your markup:

<div id="frequentlyBoughtTogether"></div>
<div id="relatedProducts"></div>

Then, insert your recommendations by calling the frequentlyBoughtTogether function and providing the container. It can be a CSS selector or an Element.

The process is the same for relatedProducts.

/** @jsx h */
import { h } from 'preact';
import {
  frequentlyBoughtTogether,
  relatedProducts,
} from '@algolia/recommend-js';
import recommend from '@algolia/recommend';

const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
const indexName = 'YOUR_INDEX_NAME';
const currentObjectID = 'YOUR_OBJECT_ID';

frequentlyBoughtTogether({
  container: '#frequentlyBoughtTogether',
  recommendClient,
  indexName,
  objectIDs: [currentObjectID],
  itemComponent({ item }) {
    return (
      <pre>
        <code>{JSON.stringify(item)}</code>
      </pre>
    );
  },
});

relatedProducts({
  container: '#relatedProducts',
  recommendClient,
  indexName,
  objectIDs: [currentObjectID],
  itemComponent({ item }) {
    return (
      <pre>
        <code>{JSON.stringify(item)}</code>
      </pre>
    );
  },
});

For React

Import the FrequentlyBoughtTogether and RelatedProducts and use them in your parent component.

import React from 'react';
import {
  FrequentlyBoughtTogether,
  RelatedProducts,
} from '@algolia/recommend-react';
import recommend from '@algolia/recommend';

const recommendClient = recommend('YourApplicationID', 'YourSearchOnlyAPIKey');
const indexName = 'YOUR_INDEX_NAME';

function App({ currentObjectID }) {
  // ...

  return (
    <div>
      <FrequentlyBoughtTogether
        recommendClient={recommendClient}
        indexName={indexName}
        objectIDs={[currentObjectID]}
        itemComponent={({ item }) => {
          return (
            <pre>
              <code>{JSON.stringify(item)}</code>
            </pre>
          );
        }}
      />
      <RelatedProducts
        recommendClient={recommendClient}
        indexName={indexName}
        objectIDs={[currentObjectID]}
        itemComponent={({ item }) => {
          return (
            <pre>
              <code>{JSON.stringify(item)}</code>
            </pre>
          );
        }}
      />
    </div>
  );
}

Continue reading our Getting Started guide.

Documentation

The documentation offers a few ways to learn about the Recommend library:

You can find more on the documentation.

Support

Packages

License

MIT

recommend's People

Contributors

dependabot[bot] avatar dfcook avatar dhayab avatar dkurzaj avatar francoischalifour avatar instantsearch-bot avatar jojva avatar marialungu avatar matthew1809 avatar mthuret avatar raed667 avatar redox avatar shipow avatar shortcuts avatar sophiemanley03 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

recommend's Issues

When no fallback filters is passed we can still get random items

When no fallback filters is passed, we are setting up the numbers of items we want based on the numbers of objectIds we retrieved as recommendations. When one of those objectIds doesn't exist anymore in the index, the results set got completed by a random object.

More impactful on FBT if one of this item doesn't exist anymore the result set will be completed by the first item of the empty query.

OR syntax with FacetFilters not working.

Calling the reco components with a search param facetFilters containing a OR condition doesn't work.
It works when the same filter is passed via the search param filters and its different syntax.

facetFilters: [
            ['named_tags.brand:Merangue'],
            'named_tags.brand:Crayola',
          ]

vs
filters: "named_tags.brand:Merangue OR named_tags.brand:Crayola"

I suppose the problem comes from the destructuration there:

https://github.com/algolia/ui-components/blob/e297a923eebab60e9227d54bd48a8e4472717be8/packages/recommendations-core/src/getRecommendations.ts#L115

Error 400 when too much multi query

Description

When using useFrequentlyBoughtTogether with more than 50 objectIDs, we receive an error responde from Algolia.
{"message":"Too many queries in multi query request","status":400}

Reproduction

Its the basic codesandbox with the objectId sent 51 times instead of once.
https://codesandbox.io/s/dreamy-keldysh-rdwthn?file=/app.tsx

Steps

  1. Open dev tools to see network request
  2. Click on the select and choose an item
  3. See error 400 in recommendations request

Expected behavior

The hook should split objectIDs in multiple batch of 50 and send multiple query to Algolia, merge the result and send back.

Environment

  • OS: Windows 10
  • Browser: Chrome
  • Library version: 114

pragma cannot be set when runtime is automatic

Discussed in #166

Originally posted by mwmwmw December 20, 2023
In NextJS 14.0.4 I have a pretty basic related posts recommender.

On Next 14.0.1 I get no error, and when I upgrade to anything > 14.0.1 (14.1.0 as of this writing) I get this error.

 ⨯ ./node_modules/.pnpm/@[email protected]/node_modules/@algolia/recommend-vdom/dist/esm/FrequentlyBoughtTogether.js
Error: 
  × pragma cannot be set when runtime is automatic
   ╭─[/home/erebus/rdar/node_modules/.pnpm/@[email protected]/node_modules/@algolia/recommend-vdom/dist/esm/FrequentlyBoughtTogether.js:1:1]
 1 │ import _extends from "@babel/runtime/helpers/extends";
 2 │ /** @jsx createElement */
   · ─────────────────────────
 3 │ import { createDefaultChildrenComponent } from './DefaultChildren';
 4 │ import { createDefaultFallbackComponent } from './DefaultFallback';
 5 │ import { createDefaultHeaderComponent } from './DefaultHeader';

If I find/replace and remove all of these pragmas, the code works fine /** @jsx createElement */

Has anyone encountered an issue like this before? I am completely stumped.

My package.json


 "dependencies": {
   "@algolia/recommend": "^4.22.1",
   "@algolia/recommend-react": "^1.12.0",
   "@headlessui/react": "^1.7.18",
   "@heroicons/react": "^2.1.1",
   "@next/bundle-analyzer": "^12.3.4",
   "@radix-ui/react-dialog": "^1.0.5",
   "@radix-ui/react-tabs": "^1.0.4",
   "@react-three/drei": "^9.96.1",
   "@react-three/fiber": "^8.15.14",
   "@storyblok/js": "^2.3.0",
   "@storyblok/react": "^2.4.8",
   "@studio-freight/hamo": "^0.6.28",
   "@tailwindcss/forms": "^0.5.7",
   "@tailwindcss/typography": "^0.5.10",
   "@types/react-dom": "^18.2.18",
   "@vercel/analytics": "^0.1.11",
   "algoliasearch": "^4.22.1",
   "axios": "^1.6.5",
   "class-variance-authority": "^0.6.1",
   "client-only": "^0.0.1",
   "clsx": "^1.2.1",
   "dotenv": "^16.3.2",
   "framer-motion": "^10.18.0",
   "google-map-react": "^2.2.1",
   "h5o": "^0.11.3",
   "instantsearch.js": "^4.64.0",
   "lucide-react": "^0.279.0",
   "next": "^14.1.0",
   "next-seo": "^6.4.0",
   "next-share": "^0.18.4",
   "next-sitemap": "^4.2.3",
   "next-themes": "^0.2.1",
   "postcss-preset-env": "^8.5.1",
   "react": "^18.2.0",
   "react-clipboard.js": "^2.0.16",
   "react-dom": "^18.2.0",
   "react-gtm-module": "^2.0.11",
   "react-hotkeys-hook": "^4.4.4",
   "react-instantsearch": "^7.5.2",
   "react-instantsearch-nextjs": "^0.1.9",
   "react-player": "^2.14.1",
   "react-select": "^5.8.0",
   "react-slugify": "^2.1.0",
   "react-textarea-autosize": "^8.5.3",
   "react-use": "^17.4.3",
   "sharp": "^0.32.6",
   "stats.js": "^0.17.0",
   "storyblok-js-client": "^6.6.3",
   "storyblok-rich-text-react-renderer": "^2.9.1",
   "tailwind-merge": "^1.14.0",
   "tailwindcss": "^3.4.1",
   "tailwindcss-animate": "^1.0.7",
   "three": "^0.158.0",
   "use-mailchimp-form": "^3.1.0",
   "zustand": "^4.4.7"
 },
 "devDependencies": {
   "@types/node": "18.11.18",
   "@types/react": "^18.2.48",
   "@typescript-eslint/eslint-plugin": "^5.62.0",
   "@typescript-eslint/parser": "^5.62.0",
   "autoprefixer": "^10.4.17",
   "cross-env": "^7.0.3",
   "cssnano": "^5.1.15",
   "eslint": "^8.56.0",
   "eslint-config-airbnb-base": "^15.0.0",
   "eslint-config-airbnb-typescript": "^17.1.0",
   "eslint-config-next": "^13.5.6",
   "eslint-config-prettier": "^8.10.0",
   "eslint-plugin-import": "^2.29.1",
   "eslint-plugin-prettier": "^5.1.3",
   "eslint-plugin-react": "^7.33.2",
   "eslint-plugin-simple-import-sort": "^7.0.0",
   "eslint-plugin-tailwindcss": "^3.14.0",
   "eslint-plugin-unused-imports": "^2.0.0",
   "npm-run-all": "^4.1.5",
   "postcss": "^8.4.33",
   "postcss-import": "^15.1.0",
   "postcss-nesting": "^10.2.0",
   "prettier": "^3.2.4",
   "rimraf": "^3.0.2",
   "typescript": "^5.3.3"

}

I have tried Node 20 and 21, npm, yarn, pnpm to run and the result is the same.

Add a global ruleContext to ease some rules

Today the widget is passing a unique ruleContext for every objectIds that have recommendations. I was thinking that we can also add one more global like "recommend" that can ease the creation of rules such as "filtering out out-of-stock items". Some search customers do this technique to remove out of stock on their search.

Recommend's hooks does not handle errors

Description

Recommend React's hooks does not gracefully handle errors, and errors cannot be caught in React's ErrorBoundary.

For more context :

We are using Algolia's recommend on production and staging environment.

The production environment's index works. The staging environment's index does not build as it has not enough data (less than 1'000 events).

However, when we are running our tests against the staging env, all requests fail because the index does not exists (as it cannot build). The problem, is that all errors cannot be caught and results in React throwing an error.

For instance, in useFrequentlyBoughtTogether.js line 42 :

useEffect(() => {
  setStatus('loading');
  getFrequentlyBoughtTogether({
    // ...
  })
    .then((response) => {
      setResult(response);
      setStatus('idle');
    })
    // missing catch, resulting in error not being catch by React
}, [
  // ...
]);

It would be great to gracefully handles errors in each hook.

Reproduction

The linked codesandbox does not work. It results with an error /app.tsx: Unexpected token (133:105).

Steps

To reproduce the error, you may :

  1. Configure recommendClient with a wrong client
  2. Use an index that does not build
  3. Ask for a non-existent objectIDs

Expected behavior

Error should be gracefully handled by React / hooks.

Environment

  • OS: macOS
  • Browser: Chrome
  • Library version: 4.14.3

useRecommendations & useRelatedProducts & useFrequentlyBoughtTogether cause infinite loop due to useEffect

Description

useRecommendations & useRelatedProducts & useFrequentlyBoughtTogether hooks are causing the app to infinitely loop due to the useEffect dependencies.

Reproduction

Very simple cra app to test reccomendations

import recommend from '@algolia/recommend';
import { useRecommendations } from '@algolia/recommend-react';

import './App.css';

const indexName = 'INDEX_NAME';
const recommendClient = recommend('APP_ ID', 'API_KEY');
const objectId = '99999999';

function App() {
  const { recommendations } = useRecommendations({
      model: 'related-products',
      recommendClient,
      indexName,
      objectIDs: [objectId],
  });

  console.log(recommendations);

  return (
    <div className="App">
      <h1>Testing Algolia Recommend</h1>
    </div>
  );
}

export default App;

Steps

  1. Run above code with correct indices/apps
  2. Application enters a full infinite loop constantly logging out recommendations.

Expected behavior

App should load once with relevant recommendations and not infinitely loop.

Environment

  • OS: macOS
  • Browser: Chrome
  • Library versions:
    "@algolia/recommend": "^4.10.3",
    "@algolia/recommend-react": "^1.0.0",

Possible Cause (We have debugged)

Currently the hooks useEffect dependency is reliant on the props object this object contains the status prop which is also set within the useEffect thus causing an infinite loop.

I need Recommendations to fetch the Recommendations record but when i used GetRecommendationsAsync as inside that pass request i get error like {"message":"Index does not exist","status":404} i double check everything like index name and api key and permissions as well. So any solution.

var requests = new List {
new RecommendRequest {
IndexName = l.Items[0].Name, //here is index name
ObjectID = "333434349435",
Model = "related-products",
Threshold = 10,
MaxRecommendations = 10,
QueryParameters = new Query(),
FallbackParameters = new Query()
}
};

        var recommendationClient = new RecommendClient(algApplicationId, algAdminApiKey);

        var res = client.GetApiKey(algAdminApiKey);

        if (res.Acl.Contains("recommendation"))
        {
            Console.WriteLine("ok");
        }

        try
        {
            
            var task = Task.Run(() => recommendationClient.GetRecommendationsAsync<NewsDetail>(requests));
            if (task.Wait(TimeSpan.FromSeconds(300)))
            {
                var response = task;
                Console.WriteLine($"ObjectID: {response}");
            }
            else
            {
                throw new Exception("Request Timed out");
            }
        }
        catch (AggregateException ex)
        {

            foreach (var inner in ex.InnerExceptions)
            {
                Console.WriteLine(inner.Message);
            }

        }

Pass a wrapper to recommendations props

sometimes you want a carousel, sometimes just a row.
sometimes you just don't want to display anything it there is nothing interesting back from reco(space is precious).
sometimes you want to replace it by a different widget.

`transformItems` does not provide a reliable data structure for `items`

Description

When using useFrequentlyBoughtTogether or useRelatedProducts, the transformItems property should allow me to retrieve the list of items, transform it and return a new list.

It appears the list of items (items) is not always an Array, making it impossible to reliably iterate over it or use any Array function (map, filter, etc.).

Reproduction

In this sandbox, the Frequently Bought Together component is wrapped in a connectStateResults connector, allowing me to retrieve the ID of the first Algolia hit.

Preview →

Steps

Just open the console and see subsequents calls to transformItems providing a wrong structure as items.

Expected behavior

items is always an Array.

Environment

  • OS: macOS
  • Browser: Chrome
  • Library version:
    • @algolia/recommend: 4.12.0
    • @algolia/recommend-react: 1.1.0
    • react-instantsearch-dom: 6.0.0

Can't import the named export 'dequal' (imported as 'dequal') from default-exporting module

Description

Getting Error in /@algolia/recommend-react/dist/esm/useStableValue.js file

Can't import the named export 'dequal' (imported as 'dequal') from default-exporting module (only default export is available)

Reproduction

Preview →

Steps

  1. Click on ...
  2. See error

Expected behavior

Environment

  • OS: [e.g., Windows / Linux / macOS / iOS / Android]
  • Browser: [e.g., Chrome, Safari]
  • Library version: [e.g., 1.0.0]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.