2

Im trying to do a RPG table using react-konva and I coudnt render images from database dynamically user the hook useImage, Its now work inside the map.

const imagens =
    tokens && tokens.tokens && tokens.tokens.map(item => item.image)

    const [token] = useImage(imagens && imagens[0])

  return (
    <Stage
      x={stagePos.x}
      y={stagePos.y}
      width={1200}
      height={600}
      draggable
      onDragEnd={e => {
        setStagePos(e.currentTarget.position())
      }}
    >
      <Layer>
        {gridComponents}

        {tokens &&
          tokens.tokens &&
          tokens.tokens.map(item => (
            <Image
              draggable
              x={item.x}
              y={item.y}
              image={token} // item.image
              width={item.width}
              height={item.height}
              offsetX={item.width / 2}
              offsetY={item.height / 2}
              scaleX={1}
              rotation={item.angle}
              onDragEnd={handleDragEnd}
              onClick={() => {
                setAngle(angle + 45)
                item.angle += 45
              }}
            />
          ))}
      </Layer>
    </Stage>

That way us working but with static image for all itens. How could I put the useImage inside de map?

I return this error message when I triedenter image description here

I also need to move each one and rotate. I did the rotate like this, looks like it worked!

 onClick={() => {
                setAngle(angle + 45)
                item.angle += 45
              }}
Rogerio Azevedo
  • 786
  • 2
  • 13
  • 32

1 Answers1

3

This is because hooks must be deterministic in their ordering. By putting a hook outside of the component, react is able to guarantee the order of the useImage hook in each render.

If you put it inside of the components props then react cannot guarantee the order; If the array changes order, or items are removed from the array then the hooks will no longer be in the same order as they were in the initial render.

Read more about why they have to be in order here: https://reactjs.org/docs/hooks-rules.html#explanation

To solve your problem, you can instead push down the useImage call into a component:

const Token = props => {
    const [tokenImg] = useImage(props.image);
    return (
       <Image
          image={tokenImg}
          / * snip */
       />
    );
}

Then in the .map:

tokens.tokens.map(item => <Token image={item.image}/>)
Dylan Kerler
  • 2,007
  • 1
  • 8
  • 23
  • Ty Dylan!!! I works like a cham! I am a bit confuse abou my functions, onclick rotattion and onDragEnd on this component way. – Rogerio Azevedo Jun 18 '20 at 12:16
  • Pass in the handleDrag and onClick function as a prop to Token too. Then you can pass in those props to the Image component. with props.handleDrag, and props.onClick – Dylan Kerler Jun 18 '20 at 14:00