pixi-react icon indicating copy to clipboard operation
pixi-react copied to clipboard

Bug: Multiple instances of Component with `Texture` via `useAssets`

Open itsezc opened this issue 1 year ago • 10 comments

Current Behavior

When you have two Pixi components with a Sprite / Texture of the same URL, it doesn't show up when Mapped, I believe this is an issue with the underlying Cache.

Expected Behavior

N/A

Steps to Reproduce

N/A

Environment

  • @pixi/react version: v8 Beta
  • pixi.js version: v8
  • React version: 18.0.0
  • ReactDOM version: 18.0.0
  • Browser & Version: Chrome 127
  • OS & Version: MacOS 14

Possible Solution

No response

Additional Information

No response

itsezc avatar Aug 29 '24 06:08 itsezc

Would you mind adding a code snippet illustrating the issue for clarity?

thejustinwalsh avatar Aug 29 '24 11:08 thejustinwalsh

As an example take the following React Component:

'use client';

import { type FC, useCallback } from 'react';

import { useAssets } from '@pixi/react';
import type { Container, Graphics } from 'pixi.js';

export namespace Character {
  export type Props = {
    name: string;
    config?: {
      x?: number;
      y?: number;
    };
  };
}

export const Character: FC<Character.Props> = ({
  name,
  config = { x: 0, y: 0 },
}) => {

  const {
    assets: [texture],
    isSuccess,
  } = useAssets([
    {
      alias: name,
      src: `/${name}.webp`
    },
  ]);

  const drawWrapper = useCallback(
    (graphics: Graphics) =>
      graphics
        .roundRect(0, 0, 40, 40, 6)
        .fill({ 0x95af94 }),
    [],
  );

  return (
    <container
      zIndex={2}
      x={config.x ?? 0}
      y={config.y ?? 0}
      scale={1}
      cursor='pointer'
      eventMode='static'
    >
      <graphics zIndex={1} draw={drawWrapper} />
      {isSuccess && (
        <sprite
          texture={texture}
          width={40}
          height={40}
          zIndex={2}
          anchor={0}
        />
      )}
    </container>
  );
};

When calling this Component with a map rendering multiple "versions" of this with the same name prop doesn't render the Sprite, but just the wrapper

itsezc avatar Aug 29 '24 13:08 itsezc

Thank you. Nice find!

I have yet to run into this specifically, as I was loading the asset in the parent component and passing the loaded texture into the child component I mapped over.

I can take a crack at adding a test case to https://github.com/pixijs/pixi-react/blob/beta/test/unit/hooks/useAssets.test.tsx. If you have any spare cycles and can capture the failure, it would greatly help expedite the fix. I can take over the failing PR.

I'm about to go on vacation and will be able to take a look at the end of next week.

thejustinwalsh avatar Aug 29 '24 14:08 thejustinwalsh

Thank you. Nice find!

I have yet to run into this specifically, as I was loading the asset in the parent component and passing the loaded texture into the child component I mapped over.

I can take a crack at adding a test case to https://github.com/pixijs/pixi-react/blob/beta/test/unit/hooks/useAssets.test.tsx. If you have any spare cycles and can capture the failure, it would greatly help expedite the fix. I can take over the failing PR.

I'm about to go on vacation and will be able to take a look at the end of next week.

No issues, so when using the useAssets with this approach, what happens is the "first component" calls the useAssets hook, and renders, but for the "second component" it returns undefined. With some debugging I can see that the Pixi Cache is being set properly, but its being removed on an additional call of useAssets

itsezc avatar Aug 29 '24 15:08 itsezc

For repro: https://codesandbox.io/p/sandbox/react-pixi-mapped-sprites-dk4jcn

itsezc avatar Aug 29 '24 15:08 itsezc

Thanks for the repro; I will probably have to mock fetch, as my current test and mocks do not appear to fail when I attempt to fail the test. Must mock deeper into the mock abyss.

thejustinwalsh avatar Aug 29 '24 19:08 thejustinwalsh

Waiting on beta 13 🚀

itsezc avatar Sep 02 '24 10:09 itsezc

I'm with beta 14 and this issue seems still present.

I looked into the source code and the problem seems happen when allAssetsAreLoaded is true (on 2nd+ load and the asset is already presented in the cache), it does nothing and returns isSuccess false with assets empty.

const [state, setState] = useState<UseAssetsResult<T>>({
    assets: Array(assets.length).fill(undefined),
    isError: false,
    isPending: true,
    isSuccess: false,
    status: UseAssetsStatus.PENDING,
});

...

const allAssetsAreLoaded = assets.some(assetsLoadedTest<T>);

if (!allAssetsAreLoaded) {
   ...
}

return state;

Meanwhile, useAsset still works well although it's marked as deprecated: Doesn't work:

const { assets: [texture], isSuccess } = useAssets(["assets/pipe-green.png"]);
return (isSuccess && <sprite texture={texture} width={10} height={50} />);

Works:

const texture = useAsset("assets/pipe-green.png");
return (<sprite texture={texture} width={10} height={50} />);

furic avatar Sep 30 '24 02:09 furic

@furic The PR that fixes this issue has not been merged yet and is still open https://github.com/pixijs/pixi-react/pull/533

thejustinwalsh avatar Sep 30 '24 04:09 thejustinwalsh

I can confirm this issue is quite blocking for pretty common use-cases. when you unmount any component that use a texture, and add it back later; it just doesn't display anymore

I'll just use the deprecated useAsset in the meantime :)

rvion avatar Oct 20 '24 10:10 rvion

I'm likely experiencing this issue as well - I'm using React Router v7, and I have an experience that uses useAssets - if I navigate away, and come back to the view that's using useAssets, the assets never load. It seems that PR #533 likely resolves the problem but I'm having trouble building pixi-react with my current setup to test...

ben-zabloski avatar Nov 29 '24 10:11 ben-zabloski

:tada: This issue has been resolved in version 8.0.0-beta.16 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket:

github-actions[bot] avatar Dec 26 '24 05:12 github-actions[bot]

:tada: This issue has been resolved in version 8.0.0 :tada:

The release is available on GitHub release

Your semantic-release bot :package::rocket:

github-actions[bot] avatar Feb 28 '25 15:02 github-actions[bot]