web-dev-qa-db-ja.com

デバッグ:ESLINT警告 "ループ内で宣言されている関数には、変数への危険な参照が含まれています... no-loop-func"

Create-react-appを使用してReactでソートビジュアライザを構築する[ https://roy-05.github.io/sort-visualizer/ ]

SetTimeoutsを使用してループの各反復をアニメーション化しています。 Dev Consoleでは、次の警告があります。

LINE 156:32:ループで宣言されている関数は、変数 ''最小値 '、'最小 '、'最小 '、'最小 'NO-LOOP-funcへの危険な参照を含みます。

これがコードスニペットです:

_for(let i=0; i<arr.length-1; i++){
            let minimum = i; //Declare minimum here
            setTimeout(()=>{
                for(let j = i+1; j<arr.length; j++){
                    setTimeout(()=>{
                        //Getting a warning for these references:
                        array_bar[j].style.backgroundColor = 'red';
                        array_bar[minimum].style.backgroundColor = 'blue';
                        setTimeout(()=>{
                            if(arr[j] < arr[minimum]){
                            array_bar[minimum].style.backgroundColor = 'lightblue';
                            minimum = j; 
                            }  
                            else{
                                array_bar[j].style.backgroundColor = 'lightblue';
                            }  
                        }, 4);
                    }, (j-1)*4);    
                }
_

eslint docs 、私は問題はSetTimeout内の値を変更しているが変数はその範囲外で宣言されていると思います。

その警告を修正する方法はよくわかりません。

注:必要な場合はこれが機能全体です -

_selectionSort(){
        const arr = this.state.array,
            array_bar = document.getElementsByClassName("array-elem");

        this.setState({startedSelectionSort: true});

        for(let i=0; i<arr.length-1; i++){
            let minimum = i; //Declare minimum here
            setTimeout(()=>{
                for(let j = i+1; j<arr.length; j++){
                    setTimeout(()=>{
                        //Getting a warning for these references:
                        array_bar[j].style.backgroundColor = 'red';
                        array_bar[minimum].style.backgroundColor = 'blue';
                        setTimeout(()=>{
                            if(arr[j] < arr[minimum]){
                            array_bar[minimum].style.backgroundColor = 'lightblue';
                            minimum = j; 
                            }  
                            else{
                                array_bar[j].style.backgroundColor = 'lightblue';
                            }  
                        }, 4);
                    }, (j-1)*4);    
                }
                setTimeout(()=>{
                    let temp = arr[i],
                    arr1_height = arr[minimum],
                    arr2_height = arr[i];

                    arr[i] = arr[minimum];
                    arr[minimum] = temp;

                    array_bar[i].style.height = `${arr1_height}px`;
                    array_bar[minimum].style.height = `${arr2_height}px`;

                    array_bar[i].style.backgroundColor = "green";
                    if(i !== minimum){
                        array_bar[minimum].style.backgroundColor = 'lightblue';
                    }
                }, 400);


                if(i === arr.length-2){
                    setTimeout(()=>{
                        array_bar[i+1].style.backgroundColor = "green";
                    },800);
                }

            }, i*400);
        }

        setTimeout(()=>{
            this.setState({sorted: true})
        }, arr.length*400+1750);

    }
_
4
roy05

setTimeoutの中の変数を変更すると問題が発生しているのは正しいです。あなたは約束の中でsetTimeoutをラッピングして、変数を変更する前にそれが解決を待っていることでこれを回避することができます。これはasync/awaitを使用してはるかにクリーンです。

for (let i = 0; i < arr.length - 1; i++) {
    let minimum = i;
    await new Promise(resolve => setTimeout(resolve, i * 400));
    for (let j = i + 1; j < arr.length; j++) {
        array_bar[j].style.backgroundColor = "red";
        array_bar[minimum].style.backgroundColor = "blue";

        await new Promise(resolve => setTimeout(resolve, (j - 1) * 400));
        if (arr[j] < arr[minimum]) {
            array_bar[minimum].style.backgroundColor = "lightblue";
            minimum = j;
        }
    }
}

各ループを使用すると、タイムアウトが期限切れになると解決する約束を作成します。 awaitを使用すると、約束が解決されるまで関数の実行を一時停止します。次に、minimumのコールバック関数の範囲内でなく、setTimeoutのような変数を変更できます。

0
red.connors