Skip to content

Setting null-initialized property causes unexpected behavior due to mutation #3574

@bigmistqke

Description

@bigmistqke

The following snippet causes unexpected behavior (imo) due to r3f mutating the target value instead of setting the property. I can only reproduce this behavior when the value is null initialized.

minimal reproduction

class CustomMaterial extends THREE.MeshBasicMaterial {
    color = null;
}

function Box() {
    const [material] = useState(() => new CustomMaterial());
    const [colors] = useState(() => [
        new THREE.Color("red"),
        new THREE.Color("white")
    ]);
    const [index, setIndex] = useState(0);

    useEffect(() => {
        setInterval(() => {
            setIndex((index) => (index + 1) % 2);
        }, 1000);
    }, []);

    return (
        <mesh>
            <boxBufferGeometry />
            <primitive
                object={material}
                color={colors[index]}
                attach="material"
            />
        </mesh>
    );
}
  1. add Color('red') to the CustomMaterial's (null initialized) color-prop
  2. after a second, call setIndex(1)
  3. Color('white') is passed to the color-prop
  4. the content of the second color is copied over to the first color
  5. now both colors are “white"
  6. the interval goes on for eternity, copying the properties of 1 white material over in the other white material

The comment above the condition that is responsible for this behavior mentions that it is likely that the property is read-only, but I am not sure why this assumption.

Any specific reason why not to do an Object.getOwnPropertyDescriptor check? Too expensive?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions