Nós vamos começar aqui criando um arquivo chamado de favoriteService.ts
Em seguida nós vamos criar aqui os métodos de pegar, setar e deletar o favorito do usuário
import api from "./api";
import * as SecureStore from "expo-secure-store";
const favoriteService = {
getFavorites: async () => {
const token = await SecureStore.getItemAsync("onebitshop-token");
const res = await api.get("/favorites", {
headers: {
Authorization: `Bearer ${token}`,
},
});
return res;
},
setFavorite: async (_id: string) => {
const token = await SecureStore.getItemAsync("onebitshop-token");
const res = await api.post(
"/favorites",
{ _id },
{
headers: {
Authorization: `Bearer ${token}`,
},
}
);
return res;
},
delFavorite: async (_id: string) => {
const token = await SecureStore.getItemAsync("onebitshop-token");
const res = await api.delete(`/favorites/${_id}`, {
headers: {
Authorization: `Bearer ${token}`,
},
});
return res;
},
};
export default favoriteService;
Agora, nós vamos passar para o nosso like em si, vamos começar criando dentro de common (Que está dentro de components) uma pasta chamada Like, e nela vamos colocar o index e o styled
Vamos começar criando o styled
import styled from "styled-components/native";
export const LikeButton = styled.TouchableOpacity``;
export const LikeImage = styled.Image.attrs({
resizeMode: "contain",
})`
width: 30px;
`;
Agora
import React, { SetStateAction, useEffect, useState } from "react";
import { LikeButton, LikeImage } from "./styled";
import favoriteService from "../../../services/favoriteService";
export interface FavoriteProps {
favorites: boolean;
productId: string;
}
const likeIcon = require("../../../../assets/icons/like.png");
const likedIcon = require("../../../../assets/icons/liked.png");
const Like = ({ favorites, productId }: FavoriteProps) => {
const [isFavorited, setIsFavorited] = useState<boolean>(false);
const FavoriteToggle = (favorited: boolean) => {
if (favorited === true) {
favoriteService.delFavorite(productId);
setIsFavorited(false);
} else {
favoriteService.setFavorite(productId);
setIsFavorited(true);
}
};
useEffect(() => {
setIsFavorited(favorites);
}, [favorites]);
return (
<>
{!isLiked ? (
<LikeButton
onPress={() => {
FavoriteToggle(isLiked);
}}
>
<LikeImage source={likeIcon} />
</LikeButton>
) : (
<LikeButton
onPress={() => {
FavoriteToggle(isLiked);
}}
>
<LikeImage source={likedIcon} />
</LikeButton>
)}
</>
);
};
export default Like;
Agora que temos o like, nós iremos colocar ele dentro dos locais onde a gente vai mostrar os nossos likes, começando pela productList, e lá nós vamos começar pegando todos os likes
Começaremos criando um state para todos os likes e também pegando o token
const ProductList = ({ products, handleGetProducts }: ProductsListProps) => {
const [favorites, setFavorites] = useState<string[]>([]);
const { token } = useAuth();
E agora iremos criar o handle que pega todos os nossos likes
const ProductList = ({ products, handleGetProducts }: ProductsListProps) => {
const [favorites, setFavorites] = useState<string[]>([]);
const { token } = useAuth();
const handleGetFavorites = async () => {
if (!token) return;
const res = await favoriteService.getFavorites();
const isLiked = res.data.map((val: Product) => {
return val._id;
});
setFavorites(isLiked);
};
Agora, nós podemos criar uma função que vai fazer uma verificação e retornar true or false de acordo com se temos ou não um like
const isFavorite = (product: Product) =>
!!favorites.find((favorite) => (product._id === favorite ? true : false));
useEffect(() => {
handleGetFavorites();
}, []);
Agora que temos essa função e estamos chamando o handle, nós vamos mandar ela para o nosso ProductCard no formato de boolean, pois é assim que a gente manda para o Like
const renderItem: ListRenderItem<Product> = ({ item }) => (
<ProductCard data={item} favorite={isFavorite(item)} />
);
Vamos para o ProductCard receber
export interface DataProps {
data: Product;
favorite: boolean;
}
const ProductCard = ({ data, favorite }: DataProps) => {
Agora que estamos com isso aqui dentro do ProductCard, podemos chamar o Like que temos componentizado e chamar para cá (Excluindo todo o resto que temos sobre like no index e excluir no styled)
</SellerInfoContainer>
<Like favorites={favorite} productId={data._id} />
</InfoLikeContainer>
</ProductInfoContainer>
</Container>
);
};
Agora, nós já temos nos produtos da home o sistema de likes corretamente. Podemos então testar, dar reload e veremos o like persistindo aqui na home
Agora, vamos em product fazer um handle para que a gente puxe se o produto atual está com like ou não. E aí vamos dar o like aqui dentro. Vamos fazer quase o mesmo handle que temos no ProductList, porém nós vamos dar um set diferente no final, já dando o true ou false
const Product = ({ route }: Props) => {
const [liked, setLiked] = useState(false);
const navigation = useNavigation<PropsStack>();
const { token } = useAuth();
const handleGetFavorites = async () => {
if (!token) return;
const res = await favoriteService.getFavorites();
const isLiked = res.data.map((val: ProductType) => {
return val._id;
});
const liked = isLiked.some((liked: string) => route.params._id === liked);
setLiked(liked);
};
useEffect(() => {
handleGetFavorites();
}, []);
Agora, precisamos apenas usar
<InfoContainer>
<Price>R$ {route.params.price}</Price>
<InteractionsContainer>
<Like favorites={liked} productId={route.params._id} />
<Button activeOpacity={0.8}>
<Share source={share} />
</Button>
</InteractionsContainer>
</InfoContainer>
Agora basta usarmos um marginLeft nesse Button e excluir o like que temos no styled
export const Button = styled.TouchableOpacity`
margin-left: 15px;
`;
Agora nós já temos tudo correto aqui no product e na home, vamos para as categorias, vamos começar por todas as categorias. Nós vamos fazer a mesma coisa que fizemos em productList e productCard
const CategorieList = ({ category }: CategoryProps) => {
const navigation = useNavigation<PropsStack>();
const [favorites, setFavorites] = useState<string[]>([]);
const { token } = useAuth();
const handleGetFavorites = async () => {
if (!token) return;
const res = await favoriteService.getFavorites();
const isLiked = res.data.map((val: Product) => {
return val._id;
});
setFavorites(isLiked);
};
const isFavorite = (product: Product) =>
!!favorites.find((favorite) => (product._id === favorite ? true : false));
useEffect(() => {
handleGetFavorites();
}, []);
Agora, iremos passar para o renderItem
const renderItem: ListRenderItem<Product> = ({ item }) => (
<CategorieCard product={item} key={item._id} favorite={isFavorite(item)} />
);
E agora receber em CategoryCard
interface ProductProps {
product: Product;
favorite: boolean;
}
const CategorieCard = ({ product, favorite }: ProductProps) => {