Tengo este componente que representa la cantidad de personas a las que les gustó el libro, sin embargo, no puedo obtener resultados consistentes en mis estados.
Aquí está mi código:
///this is for getting the book details const {id} = useParams(); const dispatch = useDispatch(); const[hasliked, sethasliked] = useState(null); useEffect(() => { const bookData = { id: id } dispatch(openBook(bookData)) }, []) ///and this is for setting the state of the component const { bookFeatured, isLoading, isSuccess, openbook, likeStatus } = useSelector(state => state.book); const { user, isError, message } = useSelector(state => state.auth); useEffect(()=>{ if(openbook.noOfLikes?.find((noOfLikes) => noOfLikes === user._id)){ sethasliked(true) }else{ sethasliked(false) } },[openbook]) const Likes = () => { return hasliked ? ( <><FaHeart fontSize="small" /> {hasliked.toString()}</> ) : ( <><FaRegHeart fontSize="small" fill='white'/> {hasliked.toString()}</> ); };el problema aquí es que obtengo un resultado inconsistente cuando obtengo el valor de const haslikes, si ya me gustó un libro, a veces me dirá que el hasliked es falso, pero a veces se convertirá en verdadero, esto hizo que obtuviera resultados diferentes cada uno vez que renderizo el componente, creo que tiene algo que ver con el retraso en useEffect debido a acciones asincrónicas, ¿hay algo que pueda hacer al respecto?
.toString() ? ¿Por qué no simplemente hacer return hasliked ? ( <><FaHeart fontSize="small" />True</> viendo como hasliked ya es cierto allí.
else{ sethasliked(false) }se puede eliminar cambiando el init a
const[hasliked, sethasliked] = useState(false);dispatch(openBook(bookData)) está devolviendo una promesa, puede configurar hasliked en un bloque .then eliminando la necesidad de un segundo efecto de uso return haslikeda esto
return hasliked && openbookPuede agregar un loading state a su componente y verificar si el estado de carga es true , luego mostrar un cargador o mostrar su componente.
const {id} = useParams(); const dispatch = useDispatch(); const[hasliked, sethasliked] = useState(null); const [loading, setLoading] = useState(false) // The loading state useEffect(() => { setLoading(true) // Setting the loading state true const bookData = { id: id } dispatch(openBook(bookData)) }, []) ///and this is for setting the state of the component const { bookFeatured, isLoading, isSuccess, openbook, likeStatus } = useSelector(state => state.book); const { user, isError, message } = useSelector(state => state.auth); useEffect(()=>{ if(openbook.noOfLikes?.find((noOfLikes) => noOfLikes === user._id)){ sethasliked(true) setLoading(false) // Setting loading state to false }else{ sethasliked(false) setLoading(false) // Setting loading state to false } },[openbook]) const Likes = () => { // show a loader if loading is true if(loading) { return <div>Loading...</div> } return hasliked ? ( <><FaHeart fontSize="small" /> {hasliked.toString()}</> ) : ( <><FaRegHeart fontSize="small" fill='white'/> {hasliked.toString()}</> ); };¿Has probado a usar setTimeout?
useEffect( () => { const tmr = setTimeout( () => { const bookData = { id: id } dispatch( openBook(bookData) ) }, 500) return () => clearTimeout(tmr); }, []) useEffect( () => { const tmr = setTimeout( () => { if (openbook.noOfLikes?.find( (noOfLikes) => noOfLikes === user._id) ) { sethasliked(true) } else { sethasliked( false) } }, 500) return () => clearTimeout(tmr); },[openbook])