所以,当我点击"Mark“按钮时,我一直在试图找出如何用新的项目重新绘制项目地图。我尝试将这些项放在一个useState中,并按一下按钮更新状态,但问题是当我设置状态时,它总是一个呈现,因为set状态是异步的。我将如何实现这一目标?
const Main: React.FC<MainProps> = (props) => {
// Get All Feeds
const feeds = trpc.feed.getAllFeeds.useQuery();
// Get Items
let unsorteditems;
if (props.FeedType == "one") {
unsorteditems = trpc.feed.getItemsFromFeed.useQuery({
feedId: props.feedId,
});
} else if (props.FeedType == "readalready") {
unsorteditems = trpc.feed.getReadItems.useQuery();
} else {
unsorteditems = trpc.feed.getFeedItemsFromAllFeeds.useQuery();
}
// Sort Items than add title, logo, and markedAsRead
const sorteditems = unsorteditems.data?.sort(
(objA, objB) => Number(objB.createdAt) - Number(objA.createdAt)
// Replace in other order to sort in reverse
);
let items = sorteditems?.map((item) => {
const feed = feeds.data?.find((feed) => feed.id == item.feedId);
return {
...item,
feedTitle: feed?.title,
feedLogoUrl: feed?.LogoUrl,
markedAsRead: false,
};
});
const feedName = items?.[0]?.feedTitle;
// Mark Read function
const markreadmutation = trpc.feed.markReadUsingUpsert.useMutation();
const onClickMarkRead = async (itemId: string) => {
markreadmutation.mutate({ itemId: itemId });
};
// I tried this but it didn't work, and I can't use state because its async and dosent update in time
function updateItems(index: number) {
const newItems = items?.map((item, i) => {
if (i == index) {
return {
...item,
markedAsRead: true,
};
} else {
return item;
}
});
items = newItems;
}
return (
<>
{/* I removed alot of code here to make it easier to understand so css may look weird */}
{/* <!-- Main --> */}
<div className="basis-5/12 border-l border-slate-300/40">
<h1 className="sticky top-0 z-50 border-b border-slate-300/40 bg-opacity-60 bg-clip-padding py-2 pl-2 text-xl font-bold backdrop-blur-xl backdrop-filter">
{props.FeedType == "one"
? feedName
: props.FeedType == "all"
? "All Feeds"
: props.FeedType == "readalready"
? "Recently Read"
: "Woops"}
</h1>
<div>
{items?.length == 0 && <p>No Items</p>}
{items?.map((item, i) => (
<div
className={`border-slate-300/4 relative flex h-28 flex-col border-b ${
item.markedAsRead ? "bg-gray-200" : "bg-white"
}`}
key={item.id}
>
{/* ^^^ If item is marked read it will be grayed out ^^^ */}
<button
onClick={() => {
// THIS BUTTON
// When I click this is should rerender the map with the item marked as read
onClickMarkRead(item.id);
updateItems(i);
}}
>
[Mark Read]
</button>
</div>
))}
</div>
</div>
</>
);
};发布于 2022-11-11 06:40:50
你最好用状态。您不能在React组件的第一次呈现时访问异步代码。为了使用项的最新值,应该将项存储在状态中,然后为异步调用和项操作(排序等)创建useCallback函数,最后在useEffect中调用该函数。看起来会是这样的:
const [items, setItems] = useState([]);
const getItems = useCallback( async() => {
const fetchedItems = await yourFetchFunction();
setItems(fetchedItems);
}, []);
useEffect(() => {
getItems();
}, [getItems]);发布于 2022-11-11 08:02:52
单击该按钮后,只应在等待突变后才调用updateItems。在当前代码中,提供同步调用它。您可以在onClickMarkRead中添加它。在其中传递索引并尝试如下所示(在updateItems设置项更新后处于状态):
const onClickMarkRead = async (itemId: string, index: number) => {
await markreadmutation.mutate({ itemId: itemId });
updateItems(index);
};如果它仍然不能工作,您可以通过jsFiddle、CodePen或GitHub向整个组件提供最新的代码更改,这样我就可以看到并最终使用它。
https://stackoverflow.com/questions/74398681
复制相似问题