Home > Net >  ReactJS Functional Component Renders Multiple Times and Setting Img Src With Props
ReactJS Functional Component Renders Multiple Times and Setting Img Src With Props

Time:08-27

I am a newbie in ReactJS and I am trying to pass an object as a props to a component. I am getting data from the .NET CORE WEB API and there is no problem about it. Here is my useEffect hook to do that:

    useEffect(() => {
      
        const response = axios.get("http://localhost:5122/GetUserInfo", { params: { userId: profileId } });
        response.then((res) => {
            setUserInfo(res.data);
        })
    }, [])

And I pass the userInfo state as props, as shown below:

    return (
        <div>
        <ProfileCard user={userInfo} />
        </div>
    );

To better understand of problem I took a screenshot of console. I am print user prop at the top of ProfileCard component. enter image description here

CodePudding user response:

Your screenshot shows that profilePicture is a filename à la 36ddd13a-d3b9-47ad-9719-7789892a1384.jpg.

  • Just doing <img src={profilePicture} /> would have your browser attempt to find the file by relative path, which is likely not to work.
  • require(...) only works for assets that are available at the build time of your React app and only for static strings due to bundling; an arbitrary filename that comes over the wire from your API won't be that.
  • If your HTTP server serves those images from under /File, then you'd need to do
    <img src={`/File/${profilePicture}`} />
    
    (or, if that HTTP server is not the same origin your React app is served from, but that http://localhost:5122/ from above),
    <img src={`http://localhost:5122/File/${profilePicture}`} />
    
    ).
    • If you're using e.g. create-react-app, then you'd need to put the file in the /public/File/ directory.

CodePudding user response:

You can't pass dynamic strings to require like require(./File/${user.profilePicture})

It maybe work sometimes, but only in some edge cases.

What you should do is tell the compiler exactly which files it needs to bundle:

const map = {
  'profilePic_1': require('./File/profilePic_1'),
  'profilePic_2': require('./File/profilePic_2'),
  // and so on...
}

By creating a map you can then "index" the bundled files based on server response.

<img src={map[user.profilePicture]} />

If you have a fairly large number of images I'd recommend dynamically loading them:

const map = {
  'profilePic_1': () => import('./File/profilePic_1'),
  'profilePic_2': () => import('./File/profilePic_2'),
  // and so on...
}

const YourComponent = ({userProfilePicture})
{
  // without placeholder
  const [url, setUrl] = useState('');

  // if you want to load a placeholder from a server
  // const [url, setUrl] = useState('http://placeholder_url');

  // if you want to bundle the placeholder
  // const [url, setUrl] = useState(require('./placeholder_url'));

  useEffect(() => {
    map[userProfilePicture]().then(setUrl);
  }, []);

  return <img src={url} alt=''/>;
}

CodePudding user response:

Please can you post the entire component with the useEffect and also the ProfileCard component.

It might be a problem with the useState. You should have something like

const [userInfo, setUserInfo] = useState<TypeOfGetUserInfo | null>(null)

In you ProfileCard you should have something like

const ProfileCard = React.FC<ProfileCardProps> = ({user}) => {


...

  return (
   ...something
  )
}
  • Related