Skip to content

Feed filtering by tags doesn't work #117

@jakubdrozdek

Description

@jakubdrozdek

Which package/packages do you use?
@stream-io/feeds-react-sdk

Describe the bug
When using feed.getOrCreate() with proper tag filtering syntax (seen in the example docs), the activities list still contains all activities, including those without the selected tag.

To Reproduce
Steps to reproduce the behavior:

  1. Create multiple activities in a single feed, with various tags, e.g., ['announcement', 'community:Giga_Jakub_Sons'], ['past-event', 'community:Giga_Jakub_Sons'].
  2. Call feed.getOrCreate({ watch: true, filter: { filter_tags: ['past-event'] } })
  3. Inspect the returned activities list

The request in Network tab looks like this:

https://feeds.stream-io-api.com/api/v2/feeds/feed_groups/community/feeds/Giga_Jakub_Sons?connection_id=68b1a542-0a1d-2c87-0300-0000019ee241&api_key=<my_api_token>


{"watch":true,"filter":{"filter_tags":["past_event"]}}

Expected behavior
It should return activities with the selected tag only, but it returns all activities.

Screenshots
Image

Version

  • SDK version: 0.1.0

Env:

Fill out what's applicable

React / JS client

  • Browser [e.g. chrome, safari]: Brave

Additional context
I copied the initializeFeed function from your example React app:

import {
  type GetOrCreateFeedRequest,
  StreamFeed,
  useClientConnectedUser,
  useFeedsClient,
} from "@stream-io/feeds-react-sdk";
import { useEffect, useMemo } from "react";

import { initializeFeed } from "./initializeFeed";

interface FeedProviderProps {
  groupId: string;
  id: string;
  children: React.ReactNode;
  options: GetOrCreateFeedRequest;
}

export function FeedProvider({ groupId, id, children, options }: FeedProviderProps) {
  const connectedUser = useClientConnectedUser();
  const client = useFeedsClient();

  const feed = useMemo(() => {
    if (!client) return null;

    return client.feed(groupId, id);
  }, [client, groupId, id]);

  useEffect(() => {
    if (!feed || !connectedUser) return;

    console.log("effect start");
    initializeFeed(feed, options);

    return () => {
      console.log("effect cleanup", feed?.state.getLatestValue().watch);
      //   if (feed?.state.getLatestValue().watch) {
      client?.stopWatchingFeed({
        feed_group_id: feed.group,
        feed_id: feed.id,
      });
      //   }
    };
  }, [client, options, feed, connectedUser]);

  if (!feed) {
    return null;
  }

  return <StreamFeed feed={feed}>{children}</StreamFeed>;
}
import type { Feed, FeedState, GetOrCreateFeedRequest } from "@stream-io/feeds-react-sdk";

const promisesByFeedId: Record<string, Promise<FeedState>> = {};

export const initializeFeed = (feed: Feed, options?: GetOrCreateFeedRequest): Promise<FeedState> => {
  const currentState = feed.state.getLatestValue();

  // TODO: find another key to consider feed "initialized"
  if (currentState.watch) {
    return Promise.resolve(currentState);
  }

  if (currentState.is_loading) {
    return new Promise((resolve) => {
      const unsubscribe = feed.state.subscribeWithSelector(
        (v) => ({ is_loading: v.is_loading }),
        ({ is_loading }) => {
          if (is_loading) return;

          unsubscribe();
          resolve(feed.state.getLatestValue());
        },
      );
    });
  }

  const removePromise = () => {
    if (typeof promisesByFeedId[feed.feed] !== "undefined") {
      delete promisesByFeedId[feed.feed];
    }
  };

  promisesByFeedId[feed.feed] = feed
    .getOrCreate(options)
    .then(() => feed.state.getLatestValue())
    .finally(removePromise);

  return promisesByFeedId[feed.feed];
};

then I used it like this:

type FilterType = "all" | "announcement" | "past_event";

function CommunityFeedPage() {
  const { communityHandle } = useCommunity();
  const [filterTag, setFilterTag] = useState<FilterType>("all");

  const filterOptions: GetOrCreateFeedRequest = useMemo(() => {
    const options: GetOrCreateFeedRequest = { watch: true };

    if (filterTag !== "all") {
      options.filter = { filter_tags: [filterTag] };
    }

    return options;
  }, [filterTag]);

return (
    <FeedProvider groupId="community" id={communityHandle} options={filterOptions}>
            <div className="flex flex-col gap-4">
              <NewFeedMessage />
              <FeedActivityTypeFilter type={filterTag} setType={setFilterTag} />
              <FeedActivitiesFromContext />
            </div>
    </FeedProvider>
  );
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions