繁体   English   中英

状态突变作为副作用?

[英]State was mutated as a side effect?

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

本质上,我有一个与此类似的代码:

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 的情况下运行它,此代码没有问题

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

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

引用传递与值传递

基本上在按引用传递,如果你创建一个变量a ,然后创建一个变量b等于a ,然后更改键/值的值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添加到grid ,然后更改grid state.base发生变异只是时间问题。

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

grid.push(base);

到:

grid.push(Object.assign([], base));

此处的对象分配将创建一个值为base 的新变量,并将其添加到网格中。 这可以防止对grid任何更改修改state.base

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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