状态被突变为副作用?

时间:2018-08-24 02:52:31

标签: javascript reactjs

我的代码遇到了一个奇怪的问题。抱歉,如果已经问过这个问题,我想搜索原因,但我什至不知道如何表达问题。

基本上,我有一个类似于以下代码:

class Component extends Component {
constructor(props) {
    super(props);
    this.state = { grid: [["", "", "", ""]], base: ["", "", "", ""]};
}

csvParse = (row, column) => e => {
    const newData = Papa.parse(e.target.value).data.filter(
        x => x.length !== 1 && x[0] !== ""
    );
    //newData will result in a 2D array such as [["1", "2", "3", "4"], ["5", "6", "7", "8"], ["9", "10", "11", "12"]]
    //newData is receiving the data from a copy and paste from a CSV file

    const { base } = this.state;
    let grid = this.state.grid

    for (let i = row; i < newData.length + row; i++) {
        for (let j = column; j < 4; j++) {
            try {
                grid[i][j] = newData[i][j];//1
            } catch (err) {
                grid.push(base);//2
                grid[i][j] = newData[i][j];//3 One of these is causing it, I don't know which
            }
        }
    }

    this.setState({grid},()=>{
        console.log(this.state.base) 
    //Actually logs ["9", "10", "11", "12"] instead of ["", "", "", ""]. Why was it mutated?
    })
};

render() {
    //The component renders a 4 X 1 grid of textareas. The number of rows will increase based on this.state.grid. Doesn't seem like its the issue.
    return (
        <Fragment>
            <Grid container>
                    {this.state.grid.map((row, rowIndex) => (
                        <Fragment key={rowIndex}>
                            <Grid item xs={3}>
                                <textarea
                                    onChange={this.csvParse(rowIndex, 0)}
                                    value={row[0]}
                                />
                            </Grid>
                            <Grid  item xs={3}>
                                <textarea
                                    onChange={this.csvParse(rowIndex, 1)}
                                    value={row[1]}
                                />
                            </Grid>
                            <Grid item xs={3}>
                                <textarea
                                    onChange={this.csvParse(rowIndex, 2)}
                                    value={row[2]}
                                />
                            </Grid>
                            <Grid item xs={3}>
                                <textarea
                                    onChange={this.csvParse(rowIndex, 3)}
                                    value={row[3]}
                                />
                            </Grid>
                        </Fragment>
                    ))}
                </Grid>
        </Fragment>
    );
}

}

每次我运行this.state.base都会更改为其他内容,例如[“”]。如果我在没有this.state.base

的情况下运行此代码,则没有问题

1 个答案:

答案 0 :(得分:2)

啊,我相信您希望state.base保持['','','','']。如果是这样,请继续阅读。否则让我知道,我们可以迭代。

要了解state.base的变化,您需要了解按引用传递和按值传递之间的区别。

参考传递与值传递

本质上是通过引用传递的,如果您创建变量a,然后创建变量b等于a,然后更改{{1 }},您还将更改a

b

按值传递时,如果您创建变量var a = {'hi': 'mom'} var b = a; a['hi'] = 'world'; console.log(b); // logs {hi: 'world'} ,然后创建等于a的变量b,然后更改a的值,则您不会更改a

b

对象var a = true; var b = a; a = false; console.log(b); // logs true; 和数组{}在JavaScript中是按引用传递的,大多数其他原始数据类型都是按值传递的。这是语言本身一个奇怪但至关重要的方面,它改变了我们编写React的方式。

这如何适用于您的情况

在您的情况下,您将[]分配给state.base,然后将base添加到base,然后突变gridgrid被突变只是时间问题。

为避免这种情况,只需更改:

state.base

收件人:

grid.push(base);

此处分配对象将创建一个新变量,其 value 为base,并将其添加到网格中。这样可以防止对grid.push(Object.assign([], base)); 所做的任何更改都可以修改grid