1

I have seen this asked before but I can't seem to be able to wrap my head around it with my situation.

I am using a search bar to filter the data down and it works but the image will not update. The URL passing to the child works fine but it's just not changing its state. I just don't really understand how to implement it.

PokemonList.jsx

import axios from "axios";
import React, { useEffect, useState } from "react";
import PokemonSprite from "./PokemonSprite";
import Card from "@material-tailwind/react/Card";
import CardBody from "@material-tailwind/react/CardBody";
import CardFooter from "@material-tailwind/react/CardFooter";
import H6 from "@material-tailwind/react/Heading6";
import Paragraph from "@material-tailwind/react/Paragraph";
import Button from "@material-tailwind/react/Button";

// const baseURL = "https://pokeapi.co/api/v2/pokemon?limit=898";
const baseURL = "https://pokeapi.co/api/v2/pokemon?limit=20";

export default function PokemonList() {
    const [post, setPost] = useState([]);
    const [searchTerm, setSearchTerm] = useState('');

    useEffect(() => {
        axios.get(baseURL).then((response) => {
            setPost(response.data.results);
        });
    }, []);

    if (!post) return <p>Sorry, no results.</p>;

    return (
        <div>
            <input type="text" placeholder="Search..." onChange={e => {setSearchTerm(e.target.value)}}/>
            {post.filter((data) => {
                if (searchTerm == "") {
                    return data;
                } else if (data.name.toLowerCase().includes(searchTerm.toLowerCase())) {
                    console.log(data);
                    return data;
                }
            }).map((data, idx) => (
                <div className="p-5">
                    <Card key={idx}>
                        <PokemonSprite url={data.url} />
                        <CardBody>
                            <H6 color="gray">{data.name}</H6>
                            <Paragraph color="gray">
                                Don't be scared of the truth because we need to restart the human
                                foundation in truth And I love you like Kanye loves Kanye I love
                                Rick Owens’ bed design but the back is...
                            </Paragraph>
                        </CardBody>

                        <CardFooter>
                            <Button color="lightBlue" size="lg" ripple="light">
                                Read More
                            </Button>
                        </CardFooter>
                    </Card>
                </div>
            ))}
        </div>
        
    );
}

PokemonSprite.jsx

import axios from "axios";
import React, { useEffect, useState } from "react";
import CardImage from "@material-tailwind/react/CardImage";

export default function PokemonList(url) {
    const [post, setPost] = useState();

    console.log(url);

    useEffect(() => {
        axios.get(url.url).then((response) => {
        //console.log(response.data);
        setPost(response.data);
        });
    }, []);

   if (!post) return <p>Sorry, no results.</p>;
  return (
      <div>
        <CardImage
            src={post.sprites.front_default}
            alt="Card Image"
        />
      </div>
  );
}
5
  • When you filter, you are getting the updated url in PokemonSprite? Commented Feb 24, 2022 at 16:30
  • @yousoumar yes. I can console.log it and its the updated URL. It's just not changing the image. I can refresh the page or make a change and save and it updates though. So I know its a state issue I just don't know how to go about it. Commented Feb 24, 2022 at 17:35
  • 1
    Yeah then it is a state issue. One thing to fix already is that you should have the key on <div className="p-5"> not on Card. Commented Feb 24, 2022 at 17:57
  • Is the Get request triggering ... Cause I suspect it might not be triggering? Commented Feb 24, 2022 at 18:12
  • @SiddharthSeth yes, get is triggered and I get the initial images. However, when I do a search the names get updated but the images do not. Commented Feb 24, 2022 at 18:31

2 Answers 2

2

Please rewrite your PokemonSprite component like this to enable re rendering on updates to the Url...

import axios from "axios";
import React, { useEffect, useState } from "react";
import CardImage from "@material-tailwind/react/CardImage";

export default function PokemonList(url) {
    const [post, setPost] = useState();

    console.log(url);
    const getUpdatedImage = async (imageUrl) => {
        const response = await axios.get(imageUrl);
        setPost(response.data);
        return post;

    }
    useEffect(() => {
        getUpdatedImage(url.url);
    }, [url]);

   if (!post) return <p>Sorry, no results.</p>;
  return (
      <div>
        <CardImage
            src={post.sprites.front_default}
            alt="Card Image"
        />
      </div>
  );
}
Sign up to request clarification or add additional context in comments.

4 Comments

hi, that didn't work. I think it may be due to getUpdatedImage(url.url) being a promise and not an object? console.log(getUpdatedImage(url.url));
I updated my answer ... Please try now and let me know
That did it! Thank you so much. Do you have an explanation of what I was doing wrong and what you did to fix my issue? Just trying to keep learning.
Your initial request was triggered as a lifecycle event in useEffect ... Since the dependencies array for it was empty it was not triggered subsequently ... The get request I mean ... So the Url was updating and initially images were fetched subsequent updates to Url caused no re fetching of images and thus re rendering...
0

You need to add the url in the dependency array to fetch the data again when it changes. Also, you may want to have a loader:

import axios from "axios";
import React, { useEffect, useState } from "react";
import CardImage from "@material-tailwind/react/CardImage";

export default function PokemonList({url}) {
    const [post, setPost] = useState();
    const [loading, setLoading] = useState(true);
    console.log(url);

    useEffect(() => {
        axios.get(url).then((response) => {
        //console.log(response.data);
        setPost(response.data);
        setLoading(false);
        });
    }, [url]);
  if(loading) return <p>Loading...</p>
  if (!post) return <p>Sorry, no results.</p>;
  return (
      <div>
        <CardImage
            src={post.sprites.front_default}
            alt="Card Image"
        />
      </div>
  );
}

2 Comments

url is getting passed in as an Object. {url: 'linktoimage.png'}
Yeah my bad. I edited my answer. You could use a destructuring for more readability.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.