SetState güncellemesi tamamlandıktan sonra bir işlevi yürütebilir miyim?


174

React JS için çok yeniyim (olduğu gibi, bugün yeni başladı). SetState'in nasıl çalıştığını tam olarak anlamıyorum. React ve Easel JS'yi kullanıcı girdisine dayalı bir ızgara çizmek için birleştiriyorum. İşte JS bölmem: http://jsbin.com/zatula/edit?js,output

İşte kod:

        var stage;

    var Grid = React.createClass({
        getInitialState: function() {
            return {
                rows: 10,
                cols: 10
            }
        },
        componentDidMount: function () {
            this.drawGrid();
        },
        drawGrid: function() {
            stage = new createjs.Stage("canvas");
            var rectangles = [];
            var rectangle;
            //Rows
            for (var x = 0; x < this.state.rows; x++)
            {
                // Columns
                for (var y = 0; y < this.state.cols; y++)
                {
                    var color = "Green";
                    rectangle = new createjs.Shape();
                    rectangle.graphics.beginFill(color);
                    rectangle.graphics.drawRect(0, 0, 32, 44);
                    rectangle.x = x * 33;
                    rectangle.y = y * 45;

                    stage.addChild(rectangle);

                    var id = rectangle.x + "_" + rectangle.y;
                    rectangles[id] = rectangle;
                }
            }
            stage.update();
        },
        updateNumRows: function(event) {
            this.setState({ rows: event.target.value });
            this.drawGrid();
        },
        updateNumCols: function(event) {
            this.setState({ cols: event.target.value });
            this.drawGrid();
        },
        render: function() {
            return (
                <div>
                    <div className="canvas-wrapper">
                        <canvas id="canvas" width="400" height="500"></canvas>
                        <p>Rows: { this.state.rows }</p>
                        <p>Columns: {this.state.cols }</p>
                    </div>
                    <div className="array-form">
                        <form>
                            <label>Number of Rows</label>
                            <select id="numRows" value={this.state.rows} onChange={ this.updateNumRows }>
                                <option value="1">1</option>
                                <option value="2">2</option>
                                <option value ="5">5</option>
                                <option value="10">10</option>
                                <option value="12">12</option>
                                <option value="15">15</option>
                                <option value="20">20</option>
                            </select>
                            <label>Number of Columns</label>
                            <select id="numCols" value={this.state.cols} onChange={ this.updateNumCols }>
                                <option value="1">1</option>
                                <option value="2">2</option>
                                <option value="5">5</option>
                                <option value="10">10</option>
                                <option value="12">12</option>
                                <option value="15">15</option>
                                <option value="20">20</option>
                            </select>
                        </form>
                    </div>    
                </div>
            );
        }
    });
    ReactDOM.render(
        <Grid />,
        document.getElementById("container")
    );

Açılır kutulardan biriyle satır veya sütun sayısını değiştirdiğinizde JS bölmesinde görebilirsiniz, ilk seferinde hiçbir şey olmaz. Bir sonraki açılır değeri değiştirdiğinizde, ızgara önceki durumun satır ve sütun değerlerine çekilir. Set.dtate tamamlanmadan önce bu this.drawGrid () işlevi yürütülüyor çünkü bu olduğunu tahmin ediyorum. Belki başka bir nedeni daha vardır?

Zaman ayırdığınız ve yardım ettiğiniz için teşekkürler!

Yanıtlar:


449

setState(updater[, callback]) zaman uyumsuz bir işlevdir:

https://facebook.github.io/react/docs/react-component.html#setstate

SetState işlemi bittikten sonra aşağıdaki callbackgibi ikinci parametreyi kullanarak bir işlevi yürütebilirsiniz :

this.setState({
    someState: obj
}, () => {
    this.afterSetStateFinished();
});

32
veya sadece this.setState ({someState: obj}, this.afterSetStateFinished);
Aleksei Prokopov

Benim belirli örnekte, muhtemelen aramak istediğiniz eklemek istiyorum this.drawGrid()içinde componentDidUpdateherhangi bir zaman, çünkü @kennedyyu önerdi gibi setStatebitti, ben (bu kodun bazı satırları tasarruf diye) ızgara yeniden çizmek istiyoruz, fakat aynı şeyi başarmak .
monalisa717

Büyük cevap ... bana çok yardımcı oldu
MoHammaD ReZa DehGhani

Benim için çok zaman kazandırıyor. Teşekkürler.
Nayan Dey

28

rendersetStatedeğişiklik olduğunda bileşeni her yeniden oluşturduğunuzda çağrılır . Çağrınızı yöntemlerinizde drawGridçağırmak yerine oraya taşırsanız, update*sorun yaşamamanız gerekir.

Bu sizin için işe yaramazsa, setStateikinci bir parametre olarak geri çağrıyı alan bir aşırı yükleme de vardır. Son çare olarak bundan yararlanabilmelisiniz.


2
Teşekkür ederim - ilk öneriniz işe yarıyor ve (çoğunlukla) mantıklı. Bunu yaptım: render: function() { this.drawGrid(); return......
monalisa717

3
Ahem, lütfen bunu yapma render()... sytolk'un cevabı kabul edilen olmalı
mfeineis

Bu yanlış bir cevaptır, setState sonsuz döngü için gidecek ve sayfayı kilitleyecektir.
Maverick

Justin, neden geri çağrının setStateson çare kullanılması gerektiğini söylediğimle ilgileniyorum . Burada çoğu insanla bu yaklaşımı kullanmanın mantıklı olduğunu kabul ediyorum.
monalisa717

1
@Rohmer, bu da her render çağrısında yürütülmesi pahalı olsa da her çağrıda da gerekli değildir. Saf reactolsaydı, vdom çoğu durumda çok fazla iş yapmamaya dikkat ederdi, bu en aza indirmek istediğiniz başka bir kütüphane ile birlikte çalışır
mfeineis

14

setStateGeri dönüş yapmakPromise

Bir geçmesinin yanı sıra callbacketmek setState()yöntemle, bir etrafına sarın asyncfonksiyonu ve kullanımı then()yöntemi - Bir temizleyici kodu üretebilir bazı durumlarda:

(async () => new Promise(resolve => this.setState({dummy: true}), resolve)()
    .then(() => { console.log('state:', this.state) });

Ve burada bir adım daha atabilir ve setStatebence yukarıdaki sürümden daha iyi olan yeniden kullanılabilir bir işlev yapabilirsiniz :

const promiseState = async state =>
    new Promise(resolve => this.setState(state, resolve));

promiseState({...})
    .then(() => promiseState({...})
    .then(() => {
        ...  // other code
        return promiseState({...});
    })
    .then(() => {...});

React 16.4'te bu iyi çalışıyor , ancak React'ın önceki sürümlerinde henüz test etmedim.

Ayrıca, geri arama kodunuzu componentDidUpdateyöntemde tutmanın çoğu durumda - muhtemelen hepsinde - daha iyi bir uygulama olduğunu belirtmek gerekir .


11

yeni sahne veya durumlar alındığında ( setStateburada aradığınız gibi ), React denilen bazı işlevleri çağırır componentWillUpdatevecomponentDidUpdate

sizin durumunuzda, sadece componentDidUpdatearamak için bir işlev ekleyinthis.drawGrid()

burada JS Bin çalışma kodu

belirttiğim gibi, kodda, componentDidUpdatesonra çağrılacakthis.setState(...)

sonra componentDidUpdateiçeride arayacakthis.drawGrid()

React bileşen Yaşam Döngüsü hakkında daha fazla bilgi https://facebook.github.io/react/docs/component-specs.html#updating-componentwillupdate


sadece bağlantıyı yapıştırmak yerine. lütfen cevaba ilgili bölümleri ekleyin.
phoenix
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.