bberak / react-native-game-engine

A lightweight Game Engine for React Native 🕹⚡🎮

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Nested entity property change doesn't trigger rerender process

AlekseiAfanasev opened this issue · comments

Hi. I'm using react-native-game-engine with Matter-js for my project. I faced with an issue of how render() is triggered.
I got entity like this:

const Entity = (
  physicsBody: Matter.Body,
  size: SizeComponent,
  color: ColorComponent
): EntityPropsType => {
  return { physicsBody, size, color };
};

And just simple renderer:

class EntityRenderer extends PureComponent<EntityPropsType> {
  render() {
    const x = this.props.physicsBody.position.x - this.props.size.width / 2;
    const y = this.props.physicsBody.position.y - this.props.size.height / 2;
    return (
      <View
        style={[
          styles.finger,
          {
            left: x,
            top: y,
            borderRadius: this.props.size.width,
            width: this.props.size.width,
            height: this.props.size.height,
          },
        ]}
      />
    );
  }
}

It is registered and works. But in my MovementSystem when I just do

entity.physicsBody.position.x = ...

it is not being rerendered.
Currently I fix this just by reassigning (and recreating, actually) color component, as it is flat.

Is it a bug or did I miss something in docs? As I see here (https://github.com/bberak/react-native-game-engine/blob/master/src/GameEngine.js#L116) it is desired behaviour. But is it valid?

I guess this is not about nested structures, but about Objects itself - when I modify physicsBody, it is not actually new object, so updateHandler does not see any changes and doesn't setState

I know I can do

entity.physicsBody = {...entity.physicsBody}

but is it the only solution?

Hey @AlekseiAfanasev,

I think a few others have faced this similar issue when using RNGE with MatterJS. As you pointed out, your entity is not being re-rendered because PureComponent will only do a shallow comparison between the current props and the next props - and seeing as they are the same object - it won't detect a change and hence skip the update.

Do the x and y properties of your entity change often? If so, then maybe switching from PureComponent to Component might be an option? Or using functional components

The other option (which probably isn't ideal) is to copy the x and y values into separate properties:

entity.physicsBody.position.x = newX
entity.physicsBody.position.y = newY
entity.x = newX
entity.y = newY

Let me know how that goes 🙏

Thank you for quick response!
Well, I totally forgot that I'm using PureComponent there instead of Component :-) Will switch