状態が変更された後にreactコンポーネントがレンダリングされない理由

受付中 プログラミング
2024-12-24
hoge
私のコードをお見せしたほうがいいです。圧縮されているので、それほど時間はかかりません。
        const PropertiesList: FC = (estatesObject) => {
            const [estates, setEstates] = useState(Object.values(estatesObject))
        
            const filterEstatesUp = () => {
                // just sorting an array of objects
                const filteredEstates = estates.sort((a, b) => parseFloat(a.price) - parseFloat(b.price))
                setEstates(filteredEstates)
            }
            const filterEstatesDown = () => {
                // just sorting an array of objects
                const filteredEstates = estates.sort((a, b) => parseFloat(b.price) - parseFloat(a.price))
                setEstates(filteredEstates) 
            }
        
            return (
                <> 
                    <div onClick={() => filterEstatesUp()}>up</div>
                    <div onClick={() => filterEstatesDown()}>down</div>
                    {estates.map((estate, index) => {
                        return(
                            <PropertyCard key={index} {...estate}/>
                        )
                    })}
                </>
            )
        }
        
したがって、問題は、これらのdivnをクリックしたときです-何も変更されませupんdown 更新x:( それが何かに役立つ場合はnext.jsを使用しています)私はあなたの推奨事項でコードを変更しましたが、私は何か他のものを手に入れました:現在状態は変化していますが、ブラウザーはまだどういうわけか私に別の不動産の順序を表示しないので、私は古い順序で残っている不動産のカードを参照してくださいこれは私の変更されたコードです:
        const PropertiesList: FC = (estatesObject) => {
            const [estates, setEstates] = useState(Object.values(estatesObject))
        
            const sortEstatesFromDown = () => {
                const sortedEstates = [...estates]
                sortedEstates.sort((a, b) => parseFloat(a.price) - parseFloat(b.price))
                console.log("FROM DOWN TO UP", sortedEstates)
                setEstates(sortedEstates)
            }
        
            const sortEstatesFromUp = () => {
                const sortedEstates = [...estates]
                sortedEstates.sort((a, b) => parseFloat(b.price) - parseFloat(a.price))
                console.log("FROM UP TO DOWN", sortedEstates)
                setEstates(sortedEstates)
            }
        
            return (
                <> 
                    <div onClick={() => sortEstatesFromDown()}>up</div>
                    <div onClick={() => sortEstatesFromUp()}>down</div>
                    {estates.map((estate) => {
                        return(
                            <PropertyCard key={estate.id} {...estate}/>
                        )
                    })}
                </>
            )
        }
        
最大価格は3.000.000、最小価格は180.000ですが、両方を順番にクリックするとわかるように、何も変更されていません。サーバーからの通常の注文があります。 この状態は正常に変更されています(コンソールから確認できます)が、ブラウザーはカードの順序を変更しません。なぜですか?
回答一覧
.sort配列をインプレースでソートします。最初にアレイのコピーを作成する必要があります。
hoge
const sortedEstates = estatesして くださいconst sortedEstates = [...estates]
hoge
しかし、それでもブラウザは正しい順序を表示しません。しかし、状態は変化しています!)
hoge
実際の更新を確認できるように、元の質問を更新してください。
hoge
console.log(index)内部estates.map((estate, index)で、インデックスがレンダリングされている順序を確認できますか。
hoge
並べ替え関数は新しい配列を作成せず、古い配列を変更します。したがって、既存の状態を再配置してから、同じ配列で状態を設定します。同じ配列であるため、reactは状態が変更されていないと見なし、レンダリングをスキップします。
        const sortedEstates = [...estates];
        sortedEstates.sort(...);
        
        setEstates(sortedEstates);
        
hoge
これで、コードは配列を変更estatesしてから同じ配列をsetEstates関数に渡すだけなので、配列の同じ参照をその関数に渡すとReactは状態を変更してはならないと判断し、再レンダリングしないため、何も変更されません。成分。 解決策は次のようになります。
        const filterEstatesUp = () => {     
            setEstates((prevEstates) => {         
                const copiedEstates = [...prevEstates];         
                return copiedEstates.sort((a, b) => parseFloat(a.price) - parseFloat(b.price)); 
            }) 
        }
        
この場合、以前の状態に依存して状態を変更するため、setStateコールバックアプローチを使用しました。また、冗長なバグを回避するために、これを使用することをお勧めします。 次に、コールバック関数で、最初に前の配列をコピーします。estatesこれは、同じ要素を使用して完全に新しい配列を作成していることを意味し、その後、コピーした配列を並べ替えて返します。 アップデートによると、estate.idすべてのエステートをマップする場所で、インデックスの代わりにキーとして使用することをお勧めします。問題はその背後に隠れていると思います。
        return (
            <> 
                <div onClick={() => sortEstatesFromDown()}>up</div>
                <div onClick={() => sortEstatesFromUp()}>down</div>
                {estates.map((estate, index) => {
                    return(
                        <PropertyCard key={estate.id} {...estate}/>
                    )
                })}
            </>
        )
        
hoge