【问题标题】:ReactJS - View not re-rendered after updating state using sliceReactJS - 使用切片更新状态后未重新渲染视图
【发布时间】:2018-05-22 11:05:13
【问题描述】:

这是我的课程Content,在App.js 中呈现。我已通读 ReactJS 教程并了解我需要更改数据而不进行突变。

https://reactjs.org/tutorial/tutorial.html

但即使我使用slice,应用程序也不会在状态更改时重新渲染。

此类管理一副纸牌,如下所示:

//omitted imports
import main_deck from ...
import side_deck from ...

export default class Content extends Component {
    constructor(props) {
        super(props);
        this.moveToMainDeck = this.moveToMainDeck.bind(this);
        this.state = {
            mainDeck : main_deck,
            sideDeck : side_deck
        }
    }

    moveToMainDeck(card) {
        const fromDeck = this.state.sideDeck.slice(); //copy the state data
        const toDeck = this.state.mainDeck.slice();

        var movable = checkMovability(fromDeck, toDeck, card);
        if (movable[0] === 1) { //use slice instead of splice
            var newMain = toDeck.slice(0, movable[1]).concat([card]).concat(toDeck.slice(movable[1]));

            var cardIndexInSideDeck = fromDeck.indexOf(card);
            var newSide = fromDeck.slice(0, cardIndexInSideDeck).concat(fromDeck.slice(cardIndexInSideDeck + 1));

            this.setState({ mainDeck : newMain, sideDeck : newSide });
        }
        else if (movable[0] === -1)
            alert("Unable to move. Main Deck is full.");
        else //movable[0] === 0
            alert("Unable to move. Limit reached for this card in Main Deck.");
    }

    render() {
        return (
            <div><MainDeck ... /><SideDeck ... /></div>
        );
    }
}

使用上面的代码,我通过打印出JSON数组来测试状态数据,在this.setState之后状态确实发生了变化,但是视图仍然没有重新渲染。

但是,我通过将slice() 替换为push() 进行了测试,状态更改后所有内容都重新渲染,如下所示:fromDeck.push(card);toDeck.push(card);

请告诉我正在使用的slice 有什么问题。非常感谢!

【问题讨论】:

    标签: reactjs setstate mutation


    【解决方案1】:

    你可以试试,as suggested here:

    const fromDeck = JSON.parse(JSON.stringify(this.state.sideDeck))
    

    这应该会创建一个全新的副本。

    【讨论】:

    • 在我的情况下它不起作用,因为对该建议的评论说它只在数组只包含原语时才有效,而不是 nullinfinite。我的json 数据有null 和非原始对象。无论如何感谢您的帮助。
    • 在这种情况下,我可能会使用cloneDeep from lodash,这样我就不必自己实现自定义函数了。
    【解决方案2】:

    这是因为 slice 函数创建了一个浅拷贝,这意味着它只复制对象的结构,这进一步意味着对象的字段不被复制,只有引用是共享的,所以当你在复制对象中更改原始对象时变化,所以当 react 比较差异时它发现没有,因此它不会重新渲染。

    //Example
    
    var one=[{'a':'first'},{'b':'second'}]
    var two=one.slice()
    var three=two.slice(0,1)
    three[0].a='third'
    
    //Now in all variables (one,two,three) a will have value of 'three'
    

    【讨论】:

    • 我明白你说的,但在代码中,我实际上并没有修改“fromDeck”和“toDeck”。相反,我声明了 2 个新变量来存储更新的数据。在“setState”之后,我打印出 Json 数据进行比较,它发生了变化,但视图没有更新。你能建议如何在 javascript 中将数据克隆到一个全新的地址吗?
    猜你喜欢
    • 1970-01-01
    • 2022-11-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-17
    相关资源
    最近更新 更多