简体   繁体   中英

Same value is updating in all the elements in the array in React

I am facing a problem. I am drawing rectangles on click and drag. I am storing these rectangles in array. Whenever I push newly made Rectangle in the array the old stored rectangles gets updated with the last pushed rectangle. For example - suppose my array(named data) contains Rectangles as - [Rectangle 1, Rectangle 2]. Now if I add 3rd rectangle the updated array is like - [rectangle 3, rectangle 3, rectangle 3]. please tell me where i am wrong and help me resolve this problem.

//I am drawing rectangles in handleMouseMove function and updating the array in handleMouseUp. I am using var data = [] to store array

import React from 'react';

var rect = {};
var shape = {};
var data = [];

export default class MyCanvas extends React.Component {
    constructor(props) {
        super (props);

        this.state = {
            imageLink : 'some link',
            shapes : [],
            isDown : false,
        };

        this.handleClick = this.handleClick.bind (this);
        this.hanldeMouseMove = this.hanldeMouseMove.bind (this);        
        this.handleMouseDown = this.handleMouseDown.bind (this);        
        this.handleMouseUp = this.handleMouseUp.bind (this);        
    }

    componentDidMount() {
        const canvas = this.refs.canvas;
        const ctx = canvas.getContext ("2d");

        const img = this.refs.image;

        canvas.height = img.height;
        canvas.width = img.width;

        img.onload = () => {
            ctx.drawImage (img, 0, 0);
        }

        var rectX = canvas.offsetLeft;
        var rectY = canvas.offsetTop;

        canvas.addEventListener ('mousemove', (e) => {this.hanldeMouseMove (e, canvas, img)}, false);
        canvas.addEventListener ('mousedown', (e) => {this.handleMouseDown (e)}, false);
        canvas.addEventListener ('mouseup', () => {this.handleMouseUp(canvas)}, false);
    }

    hanldeMouseMove(e, canvas, img) {
        if (this.state.isDown) {
            rect.w = (e.pageX - canvas.offsetLeft) - rect.startX;
            rect.h = (e.pageY - canvas.offsetTop) - rect.startY ;

            const ctx = canvas.getContext ("2d");

            // Rectangles are drawn here
            ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
            ctx.drawImage(img, 0, 0);
            ctx.strokeRect (rect.startX, rect.startY, rect.w, rect.h);

            shape = rect;
        }
    }

    handleMouseDown(e) {
        rect.startX = e.offsetX;
        rect.startY = e.offsetY;
        this.setState ({isDown : true});

    }

    // updating the array here
    handleMouseUp(canvas) {
        this.setState ({isDown : false});
        data.push(shape);
        console.log(data);
    }

    render() {
        return (
            <div className="container">
                <canvas ref = "canvas" />
                <img ref = "image" alt = "Link is Broken" src = {this.state.imageLink} className = "d-none" />
            </ div>
        );
    }
}

There is single referance for rect and its getting copied and updated everytime in the array.So,all element in the array show same element.

instead of

shape = rect;

do liek this,

shape = Object.assign({},rect);

Data object should be in your state and you have to keep in mind that React works with immutable objects.

 handleMouseUp(canvas) {
    var newDataArray = this.state.data.slice();    
    newDataArray.push(shape);   
    this.setState({data:newDataArray})  
 }  

this.state.data.slice() creates a shallow copy of the array, making it immutable

With ES6, you can also use the better way, which is

handleMouseUp(canvas) {
    this.setState(previousState => ({
        data: [...previousState.data, shape]
    }));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM