mirror of https://github.com/usememos/memos.git
fix(web): resolve MobX observable reactivity issue in filter computation
Fixes filtering functionality that was broken due to improper use of useMemo with MobX observables. The issue occurred because useMemo's dependency array uses reference equality, but MobX observable arrays are mutated in place (reference doesn't change when items are added/removed). Changes: - Remove useMemo from filter computation in Home, UserProfile, and Archived pages - Calculate filters directly in render since components are already MobX observers - Fix typo: memoFitler -> memoFilter in Archived.tsx This ensures filters are recalculated whenever memoFilterStore.filters changes, making tag clicks and other filter interactions work correctly. Fixes #5189 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
46ce0bc62e
commit
e0b1153269
|
|
@ -382,10 +382,10 @@ func (r *renderer) renderElementInCondition(cond *ElementInCondition) (renderRes
|
|||
sql := fmt.Sprintf("%s LIKE %s", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`%%"%s"%%`, str)))
|
||||
return renderResult{sql: sql}, nil
|
||||
case DialectMySQL:
|
||||
sql := fmt.Sprintf("JSON_CONTAINS(%s, %s)", jsonArrayExpr(r.dialect, field), r.addArg(str))
|
||||
sql := fmt.Sprintf("JSON_CONTAINS(%s, %s)", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`"%s"`, str)))
|
||||
return renderResult{sql: sql}, nil
|
||||
case DialectPostgres:
|
||||
sql := fmt.Sprintf("%s @> jsonb_build_array(%s::json)", jsonArrayExpr(r.dialect, field), r.addArg(str))
|
||||
sql := fmt.Sprintf("%s @> jsonb_build_array(%s::json)", jsonArrayExpr(r.dialect, field), r.addArg(fmt.Sprintf(`"%s"`, str)))
|
||||
return renderResult{sql: sql}, nil
|
||||
default:
|
||||
return renderResult{}, errors.Errorf("unsupported dialect %s", r.dialect)
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ func TestConvertExprToSQL(t *testing.T) {
|
|||
{
|
||||
filter: `"work" in tags`,
|
||||
want: "JSON_CONTAINS(JSON_EXTRACT(`memo`.`payload`, '$.tags'), ?)",
|
||||
args: []any{"work"},
|
||||
args: []any{`"work"`},
|
||||
},
|
||||
{
|
||||
filter: `size(tags) == 2`,
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ func TestConvertExprToSQL(t *testing.T) {
|
|||
{
|
||||
filter: `"work" in tags`,
|
||||
want: "memo.payload->'tags' @> jsonb_build_array($1::json)",
|
||||
args: []any{"work"},
|
||||
args: []any{`"work"`},
|
||||
},
|
||||
{
|
||||
filter: `size(tags) == 2`,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import dayjs from "dayjs";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMemo } from "react";
|
||||
import { MemoRenderContext } from "@/components/MasonryView";
|
||||
import MemoView from "@/components/MemoView";
|
||||
import PagedMemoList from "@/components/PagedMemoList";
|
||||
|
|
@ -14,7 +13,8 @@ import { Memo } from "@/types/proto/api/v1/memo_service";
|
|||
const Archived = observer(() => {
|
||||
const user = useCurrentUser();
|
||||
|
||||
const memoFitler = useMemo(() => {
|
||||
// Build filter from active filters - no useMemo needed since component is MobX observer
|
||||
const buildMemoFilter = () => {
|
||||
const conditions = [`creator_id == ${extractUserIdFromName(user.name)}`];
|
||||
for (const filter of memoFilterStore.filters) {
|
||||
if (filter.factor === "contentSearch") {
|
||||
|
|
@ -24,7 +24,9 @@ const Archived = observer(() => {
|
|||
}
|
||||
}
|
||||
return conditions.length > 0 ? conditions.join(" && ") : undefined;
|
||||
}, [memoFilterStore.filters]);
|
||||
};
|
||||
|
||||
const memoFilter = buildMemoFilter();
|
||||
|
||||
return (
|
||||
<PagedMemoList
|
||||
|
|
@ -47,7 +49,7 @@ const Archived = observer(() => {
|
|||
}
|
||||
state={State.ARCHIVED}
|
||||
orderBy={viewStore.state.orderByTimeAsc ? "pinned desc, display_time asc" : "pinned desc, display_time desc"}
|
||||
filter={memoFitler}
|
||||
filter={memoFilter}
|
||||
/>
|
||||
);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import dayjs from "dayjs";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useMemo } from "react";
|
||||
import { MemoRenderContext } from "@/components/MasonryView";
|
||||
import MemoView from "@/components/MemoView";
|
||||
import PagedMemoList from "@/components/PagedMemoList";
|
||||
|
|
@ -23,7 +22,8 @@ const Home = observer(() => {
|
|||
const user = useCurrentUser();
|
||||
const selectedShortcut = userStore.state.shortcuts.find((shortcut) => getShortcutId(shortcut.name) === memoFilterStore.shortcut);
|
||||
|
||||
const memoFilter = useMemo(() => {
|
||||
// Build filter from active filters - no useMemo needed since component is MobX observer
|
||||
const buildMemoFilter = () => {
|
||||
const conditions = [`creator_id == ${extractUserIdFromName(user.name)}`];
|
||||
if (selectedShortcut?.filter) {
|
||||
conditions.push(selectedShortcut.filter);
|
||||
|
|
@ -52,7 +52,9 @@ const Home = observer(() => {
|
|||
}
|
||||
}
|
||||
return conditions.length > 0 ? conditions.join(" && ") : undefined;
|
||||
}, [memoFilterStore.filters, selectedShortcut?.filter]);
|
||||
};
|
||||
|
||||
const memoFilter = buildMemoFilter();
|
||||
|
||||
return (
|
||||
<div className="w-full min-h-full bg-background text-foreground">
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ import copy from "copy-to-clipboard";
|
|||
import dayjs from "dayjs";
|
||||
import { ExternalLinkIcon } from "lucide-react";
|
||||
import { observer } from "mobx-react-lite";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { MemoRenderContext } from "@/components/MasonryView";
|
||||
|
|
@ -43,7 +43,8 @@ const UserProfile = observer(() => {
|
|||
});
|
||||
}, [params.username]);
|
||||
|
||||
const memoFilter = useMemo(() => {
|
||||
// Build filter from active filters - no useMemo needed since component is MobX observer
|
||||
const buildMemoFilter = () => {
|
||||
if (!user) {
|
||||
return undefined;
|
||||
}
|
||||
|
|
@ -57,7 +58,9 @@ const UserProfile = observer(() => {
|
|||
}
|
||||
}
|
||||
return conditions.length > 0 ? conditions.join(" && ") : undefined;
|
||||
}, [user, memoFilterStore.filters]);
|
||||
};
|
||||
|
||||
const memoFilter = buildMemoFilter();
|
||||
|
||||
const handleCopyProfileLink = () => {
|
||||
if (!user) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue