重新渲染后保留道具吗?

时间:2020-02-20 16:05:35

标签: javascript reactjs

我正在为我正在工作的网站实施一项新功能。基本上,有一些带有水箱清单的钻机。我添加了拆分这些储罐的功能,之后,新的拆分储罐将出现在特定钻机的储罐列表的底部。以下是我的主要组件:

export default class Drilling extends Component {

    constructor(props) {

        super(props);

        var userID = 'tgoodell';
        // call API to get default scenario
        const scenario = getDrillsDataSync(userID);
        console.log(`scenario rigs: ` + scenario);
        //var sortByProperty = function (property) {
        //return function (x, y) {
        //return ((x[property] === y[property]) ? 0 : ((x[property] > y[property]) ? 1 : -1));
        //};
        //};
        //dataset.sort(sortByProperty(`rig`));
        //console.log(dataset);

        const dataset = parseDrillingDefault(scenario);
        console.log(`parsed scenario rigs: ` + dataset);

        localStorage.setItem('rig_order', JSON.stringify(dataset));
        //console.log('------retrieving from local storage------');
        //console.log('rig_order='+ localStorage.getItem('rig_order'));

        // construct proper formatted rigs.json
        //const rigs = DrillsAdapter.getData(API.getRigsData());
        const rigs = DrillsAdapter.getData(JSON.parse(dataset));
        //rigs.sort(sortByProperty(`rigID`));
        //console.log(rigs);

        this.state = {
            rigCount: rigs.length,
            rigs: [...rigs, { rigID: 'hold', tanks: [] }],
            loading: false,
            texts: [],
            numWells: 0,
            splitTankCount: 0
        };


        //Possible tank color implementation
        // this.state.rigs.find(e => e.rigID === 'hold').tanks.map((tank, i) => {
        //     tankMap.set(tank.drill_tank, colors.pop());
        // });

        // this.state.rigs.find(e => e.rigID !== 'hold').tanks.map((tank, i) => {
        //     tankMap.set(tank.drill_tank, colors.pop());
        // });

        this.onRun = this.onRun.bind(this);
        this.handleNewSplitTank = this.handleNewSplitTank.bind(this);
        this.addNewRig = this.addNewRig.bind(this);
        console.log(`rigs state` + this.state.rigs);

    }

    addRigClick = () => {
        console.log(this.state.rigs);
        this.addNewRig();
        this.setState({
            rigs: [...this.state.rigs, { rigID: this.state.rigCount, tanks: [] }],
            rigCount: this.state.rigCount + 1,
        });
        console.log(this.state.rigs);
    };

    removeRigClick = () => {
        console.log(this.state.rigs);
        if (this.state.rigs[this.state.rigCount].tanks.length == 0) {
            var element = this.state.rigs.pop();
            this.setState({
                rigs: this.state.rigs,
                rigCount: this.state.rigCount - 1
            });
        }
        console.log(this.state.rigs);
    };

    addNewRig() {
        let xhr = new XMLHttpRequest();

        xhr.open('POST', `${options.url}/add_new_rig`, false);
        xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
        xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');

        let userId = prompt("UserID:");
        let rigName = prompt("Rig Name:");
        let rigStartDate = prompt("Rig start date");

        let queryStr = "userIDStr=" + userId + "&rigNameStr=" + rigName + "&rigStartDateStr=" + rigStartDate;

        try {
            xhr.send(queryStr);
            if (xhr.status !== 200) {
                console.log(`Error ${xhr.status}: ${xhr.statusText}`);
            } else {
                console.log('Success!');
                alert('Success. Rig added.');
            }
        } catch (err) {
            console.log('Request failed');
        }
        return xhr.response;
    }

    onDragEnd = (result) => {
        const { source, destination } = result;

        if (!destination) {
            return;
        }

        //SPREAD IT!!
        let rigsCopy = [...this.state.rigs];

        // console.log(source.droppableId);
        // console.log(destination.droppableId);

        if (source.droppableId === destination.droppableId) {
            let index = rigsCopy.findIndex(e => e.rigID == source.droppableId);
            let arr = rigsCopy[index].tanks;
            console.log(arr);
            let temp = arr.splice(source.index, 1);     //is array of 1 element
            arr.splice(destination.index, 0, temp[0]);
            rigsCopy[index].tanks = arr;
            this.setState({ rigs: rigsCopy });

        } else {//dragging to new rig         
            //console.log(`rigs=`+JSON.stringify(rigsCopy));         
            let index1 = rigsCopy.findIndex(e => e.rigID == source.droppableId);
            //console.log(`index1=`+index1);
            let index2 = rigsCopy.findIndex(e => e.rigID == destination.droppableId);
            //console.log(`index2=`+index1);
            let arr1 = [...rigsCopy[index1].tanks];
            let arr2 = [...rigsCopy[index2].tanks];
            let temp = arr1.splice(source.index, 1);
            arr2.splice(destination.index, 0, temp[0]);
            //arr2.push(temp[0]);
            //console.log(`temp0=`+JSON.stringify(temp[0]));
            rigsCopy[index1].tanks = arr1;
            rigsCopy[index2].tanks = arr2;
            this.setState({ rigs: rigsCopy });
            //console.log(`rigs_after_drop=`+JSON.stringify(rigsCopy));
        }
    };


    componentDidMount() {
        //jQuery for synchronous scrolling of tanks
        $('.tankListDiv').scroll(e => {
            $('.timeline').scrollTop(e.target.scrollTop);
        });

        this.state.rigs.find(e => e.rigID === 'hold').tanks.map((tank, i) => {
            if (tankMap.has(tank.drill_tank)) {
                return;
            }
            tankMap.set(tank.drill_tank, colors[i + 100]);
        });
    }

    onRun() {
        //Display loader after button click
        this.setState({ loading: true }, () => {
            setTimeout(() => Run(this.state.rigs), 4000);
        });
        setTimeout(() => this.setState({ loading: false }), 8000);

    }

    handleNewSplitTank() {
        this.setState({ splitTankCount: this.state.splitTankCount + 1 });
    }

    render() {
        return (
            <DragDropContext onDragEnd={this.onDragEnd}>
                <h4 id="listOfTanks"> </h4>
                <div className='rigsDiv'>
                    <button id='updatebtn' type='button' onClick={this.handleNewSplitTank}>Update</button>
                    {this.state.rigs.filter(e => e.rigID !== 'hold').map((rig, i) =>
                        <Rig rig={rig} allRigs={this.state.rigs} index={i} splitTanks={this.state.newSplitTanks} addNew={this.handleNewSplitTank} />
                    )}
                    <Fab size="small" color="secondary" aria-label="add" className='addRigBtn'
                        onClick={this.addRigClick}>
                        <AddIcon />
                    </Fab>
                    <Fab size="small" color="secondary" aria-label="remove" className='removeRigBtn'
                        onClick={this.removeRigClick}>
                        <RemoveIcon />
                    </Fab>
                    <Button onClick={this.onRun} variant="contained" className='runBtn'>RUN</Button>
                    <Divisions />
                </div>
                <div id='spinner'><BeatLoader color='blue' css={loadStyle} loading={this.state.loading} /></div>

                <Droppable droppableId='hold' className='drop'>
                    {(provided, snapshot) => (
                        <div ref={provided.innerRef} className='holder'>
                            {this.state.rigs.find(e => e.rigID == 'hold').tanks.map((tank, i) =>
                                <Tank tank={tank} index={i} />
                            )}
                            {provided.placeholder}
                            <TankMenu menuId='tank-menu' />
                            <RigMenu menuId='rig-menu' />
                        </div>
                    )}
                </Droppable>
                <div class='timeline'>
                    <Timeline />
                </div>
            </DragDropContext>
        )
    }
}

钻机组件:

function Rig(props) {

    //const forceUpdate = useForceUpdate();

    for (let i = 0; i < 700; ++i) {
        colors.push(rainbow(700, i));
    }
    shuffleArray(colors);
    props.rig.tanks.map((tank, i) => {
        if (tankMap.has(tank.drill_tank)) {
            return;
        }
        tankMap.set(tank.drill_tank, colors[i]);
    });

    const handleRigEvent = e => {
        e.preventDefault();
        contextMenu.show({
            id: 'rig-menu',
            event: e,
            props: props.rig
        });
    }


    return (
        <div className='rigDiv'>
            <div className='rigName' onContextMenu={handleRigEvent}>
                Rig {props.rig.rigID + 1}
            </div>

            <Droppable droppableId={String(props.rig.rigID)}>
                {(provided, snapshot) => (
                    <div ref={provided.innerRef} className='tankListDiv' id={props.index}>
                        {props.rig.tanks.map((tank, i) =>
                            <Tank tank={tank} index={i} rig={props} splitTanks={props.splitTanks} color={tankMap.get(tank.drill_tank)} />
                        )}
                        {provided.placeholder}
                    </div>
                )}
            </Droppable>
            <button type='button' onClick={props.addNew}>Update Rigs</button>

        </div>
    )
}

坦克组件:

const Tank = React.memo(function Tank(props) {
    let texts = [];
    let numWells = 0;

    props.tank.s_tanks.forEach((s_tank, i) => {
        texts.push('Split Tank: \n');
        texts.push(s_tank.splitted_drill_tank + "\n");
        texts.push('---------------------------');
        texts.push(' Wells:');
        s_tank.wells.forEach(well => {
            texts.push("\n" + well.well_name);
            numWells++;
            texts.push("\n");
        });
    });

    //Handler to show right click menu
    const handleTankEvent = e => {
        e.preventDefault();
        contextMenu.show({
            id: 'tank-menu',
            event: e,
            props: props.rig
            //props: props.tank
        });
    }

    function makeid(length) {
        var result = '';
        var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        var charactersLength = characters.length;
        for (var i = 0; i < length; i++) {
            result += characters.charAt(Math.floor(Math.random() * charactersLength));
        }
        return result;
    }

    return (
        <Draggable
            key={props.tank.tankID}
            draggableId={makeid(6)}
            index={props.index}
        >
            {(provided, snapshot) => {
                const style = {
                    height: !props.color ? unusedHeight : numWells + 2 + 'rem',
                    backgroundColor: props.color,
                    ...provided.draggableProps.style,
                };
                return (
                    <div
                        id='tank'
                        className='tankdiv'
                        ref={provided.innerRef}
                        onContextMenu={handleTankEvent}
                        {...provided.draggableProps}
                        {...provided.dragHandleProps}
                        style={style}
                    >
                        <div className='tooltip'>
                            {texts.map(e => <div>{e}</div>)}
                        </div>
                        {provided.placeholder}
                        {props.tank.drill_tank}
                    </div>
                );
            }}
        </Draggable>
    )
});

重新渲染Tank组件时,对于Tank组件中的以下代码块,我收到一条错误消息:“无法读取每个未定义的属性”:

props.tank.s_tanks.forEach((s_tank, i) => {
        texts.push('Split Tank: \n');
        texts.push(s_tank.splitted_drill_tank + "\n");
        texts.push('---------------------------');
        texts.push(' Wells:');
        s_tank.wells.forEach(well => {
            texts.push("\n" + well.well_name);
            numWells++;
            texts.push("\n");
        });
    });

任何帮助将不胜感激,因为这是一项关键功能。预先感谢。

0 个答案:

没有答案