react(+ typecript)组件在更新上下文时不重新启动
我有一个lainingitem
组件,该组件使用react.Context
获取并将信息设置为/从本地存储中设置。
我要实现的目标是,当组件更新上下文(和本地存储)时,我希望它使用新信息来启动,以便它更新本地按钮的状态。
问题是,尽管上下文似乎已更新以及本地存储的内容,但该项目没有启用。 (但是,当我刷新页面时,我可以看到按钮已更改状态,但是,它表明它可以从上下文中得出这些信息
。 ,我非常感谢您的帮助:)
上下文提供商设置
type FavoritesContextType = {
favorites: Favorites;
updateFavorites: (category: StorageCategory, item: string) => void;
};
export const FavoritesContext = createContext<FavoritesContextType>(
{} as FavoritesContextType
);
const FavoritesProvider: FC = ({ children }) => {
const [favorites, setFavorites] = useState<Favorites>(
getFromLocalStorage(SOME_CONSTANT)
);
const updateFavorites = (category: StorageCategory, item: string) => {
updateLocalStorage(category, item);
setFavorites(favorites);
};
return (
<FavoritesContext.Provider value={{ favorites, updateFavorites }}>
{children}
</FavoritesContext.Provider>
);
};
export const useFavoritesContext = () => useContext(FavoritesContext);
app.tsx
export const App = () => {
return (
<FavoritesProvider>
{/* Some routing wrapper and a few routes each rendering a component */}
<Route path="/launches" element={<Launches />} />
</FavoritesProvider>
)
启动.tsx fairs
export const LaunchItem = ({ launch }: LaunchItemProps) => {
const { favorites, updateFavorites } = useFavoritesContext();
const [isFavorite, setIsFavorite] = useState(false);
useEffect(() => {
if (favorites) {
setIsFavorite(
favorites.launches.includes(launch.flight_number.toString())
);
}
}, [favorites]);
return (
{/* The rest of the component, irrelevant */}
<FavoriteButton
isFavorite={isFavorite}
updateFavorites={() => {
updateFavorites(
StorageCategory.Launches,
launch.flight_number.toString()
);
}}
/>
)
faivybutton.tsx
export const FavoriteButton = ({
isFavorite,
updateFavorites,
}: FavoriteButtonProps) => {
const handleClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
e.preventDefault();
updateFavorites();
};
return (
// Using Link vs a Button to be able to preventDefault of parent Link
<Link
onClick={handleClick}
>
{/* The rest of the component, irrelevant */}
I have a LaunchItem
component which uses React.Context
to get and set information to/from the local storage.
What I am trying to achieve is that, when the component updates the Context (and local storage), I want it to rerender with the new information, so that it then updates the state of a local button.
The problem is, although the Context seems to be updated as well as the contents of the local storage, the item is not rerendered. (when I refresh the page I can see the button has changed state, however, signifying that it is able to derive that information from the Context just fine.
I will now share some code and hopefully someone is able to understand what I might be missing, I thoroughly appreciate your help :)
Context provider setup
type FavoritesContextType = {
favorites: Favorites;
updateFavorites: (category: StorageCategory, item: string) => void;
};
export const FavoritesContext = createContext<FavoritesContextType>(
{} as FavoritesContextType
);
const FavoritesProvider: FC = ({ children }) => {
const [favorites, setFavorites] = useState<Favorites>(
getFromLocalStorage(SOME_CONSTANT)
);
const updateFavorites = (category: StorageCategory, item: string) => {
updateLocalStorage(category, item);
setFavorites(favorites);
};
return (
<FavoritesContext.Provider value={{ favorites, updateFavorites }}>
{children}
</FavoritesContext.Provider>
);
};
export const useFavoritesContext = () => useContext(FavoritesContext);
App.tsx
export const App = () => {
return (
<FavoritesProvider>
{/* Some routing wrapper and a few routes each rendering a component */}
<Route path="/launches" element={<Launches />} />
</FavoritesProvider>
)
Launches.tsx
export const LaunchItem = ({ launch }: LaunchItemProps) => {
const { favorites, updateFavorites } = useFavoritesContext();
const [isFavorite, setIsFavorite] = useState(false);
useEffect(() => {
if (favorites) {
setIsFavorite(
favorites.launches.includes(launch.flight_number.toString())
);
}
}, [favorites]);
return (
{/* The rest of the component, irrelevant */}
<FavoriteButton
isFavorite={isFavorite}
updateFavorites={() => {
updateFavorites(
StorageCategory.Launches,
launch.flight_number.toString()
);
}}
/>
)
FavoriteButton.tsx
export const FavoriteButton = ({
isFavorite,
updateFavorites,
}: FavoriteButtonProps) => {
const handleClick = (e: React.MouseEvent<HTMLAnchorElement, MouseEvent>) => {
e.preventDefault();
updateFavorites();
};
return (
// Using Link vs a Button to be able to preventDefault of parent Link
<Link
onClick={handleClick}
>
{/* The rest of the component, irrelevant */}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
似乎在您的
updateFavorites
函数中,您正在调用setFavorites
,并传递在现有fairting> fairite
值中。尝试将您的updateFavorites
函数编写为:您可以通过其他方法确定将哪种值传递给
setFavorites
,但是我将您的getfromlocalstorage
函数重复使用。不确定您如何确定该状态价值。通过这样做,您将确保您要在
setFavorites
中设置的值与现有fairter
值并不相同,因此您将触发RE -使成为。It seems as though in your
updateFavorites
function you're callingsetFavorites
and passing in the existingfavorites
value. Try instead writing yourupdateFavorites
function as:There are other ways you could determine what value to pass to
setFavorites
but I reused yourgetFromLocalStorage
function as I'm not sure how you're determining that state value.By doing it this way you'll ensure that the value you're setting in
setFavorites
isn't the same as the existingfavorites
value and thus you'll trigger a re-render.