簡體   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