Saya mencoba mempelajari kait dan useState
metode ini membuat saya bingung. Saya menetapkan nilai awal ke keadaan dalam bentuk array. Metode yang diset di useState
tidak berfungsi untuk saya bahkan dengan spread(...)
atau without spread operator
. Saya telah membuat API di PC lain yang saya panggil dan mengambil data yang ingin saya setel ke status.
Ini kode saya:
import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
const StateSelector = () => {
const initialValue = [
{
category: "",
photo: "",
description: "",
id: 0,
name: "",
rating: 0
}
];
const [movies, setMovies] = useState(initialValue);
useEffect(() => {
(async function() {
try {
//const response = await fetch(
//`http://192.168.1.164:5000/movies/display`
//);
//const json = await response.json();
//const result = json.data.result;
const result = [
{
category: "cat1",
description: "desc1",
id: "1546514491119",
name: "randomname2",
photo: null,
rating: "3"
},
{
category: "cat2",
description: "desc1",
id: "1546837819818",
name: "randomname1",
rating: "5"
}
];
console.log(result);
setMovies(result);
console.log(movies);
} catch (e) {
console.error(e);
}
})();
}, []);
return <p>hello</p>;
};
const rootElement = document.getElementById("root");
ReactDOM.render(<StateSelector />, rootElement);
The setMovies(result)
serta setMovies(...result)
tidak bekerja. Bisa menggunakan bantuan di sini.
Saya berharap variabel hasil didorong ke array film.
sumber
useEffect
mungkin bukan solusi terbaik, karena tidak mendukung panggilan tidak sinkron. Jadi, jika kami ingin membuat validasi asinkron padamovies
perubahan status, kami tidak memiliki kendali atasnya.the updater provided by useState hook
asinkron atau tidak , tidak sepertithis.state
yang bisa dimutasi jikathis.setState
sinkron, Penutupanconst movies
akan tetap sama bahkan jikauseState
menyediakan fungsi sinkron - lihat contoh dalam jawaban sayasetMovies(prevMovies => ([...prevMovies, ...result]));
bekerja untuk sayaRincian tambahan untuk jawaban sebelumnya :
Sementara Bereaksi ini
setState
adalah asynchronous (kedua kelas dan kait), dan itu tergoda untuk menggunakan fakta bahwa untuk menjelaskan perilaku yang diamati, itu bukan alasan mengapa hal itu terjadi.TLDR: Alasannya adalah cakupan penutupan di sekitar
const
nilai yang tidak berubah .Solusi:
baca nilai dalam fungsi render (tidak di dalam fungsi bersarang):
tambahkan variabel ke dependensi (dan gunakan aturan eslint react-hooks / exhaustive-deps ):
gunakan referensi yang bisa berubah-ubah (bila hal di atas tidak mungkin):
Penjelasan mengapa itu terjadi:
Jika async adalah satu-satunya alasan, itu mungkin
await setState()
.Howerver, baik
props
danstate
yang diasumsikan tidak berubah selama 1 render .Dengan kait, asumsi ini ditingkatkan dengan menggunakan nilai konstan dengan
const
kata kunci:Nilai mungkin berbeda antara 2 render, tetapi tetap konstan di dalam render itu sendiri dan di dalam setiap penutupan (fungsi yang hidup lebih lama bahkan setelah render selesai, misalnya
useEffect
, penangan acara, di dalam Janji atau setTimeout apa pun).Pertimbangkan untuk mengikuti implementasi React-like palsu, tetapi sinkron , seperti:
sumber
Saya baru saja selesai menulis ulang dengan useReducer, mengikuti artikel @kentcdobs (ref di bawah) yang benar-benar memberi saya hasil yang solid yang tidak menderita sedikit pun dari masalah penutupan ini.
lihat: https://kentcdodds.com/blog/how-to-use-react-context-effectively
Saya memadatkan boilerplate-nya yang dapat dibaca ke tingkat DRYness yang saya sukai - membaca implementasi sandbox-nya akan menunjukkan kepada Anda bagaimana cara kerjanya.
Selamat menikmati, saya tahu saya !!
dengan penggunaan yang mirip dengan ini:
Sekarang semuanya tetap lancar di mana-mana di semua halaman saya
Bagus!
Kent terima kasih!
sumber
Sekarang Anda harus melihat, bahwa kode Anda benar - benar berfungsi. Yang tidak berfungsi adalah
console.log(movies)
. Ini karenamovies
menunjuk ke keadaan lama . Jika Anda memindahkan bagianconsole.log(movies)
luaruseEffect
, tepat di atas pengembalian, Anda akan melihat objek film yang diperbarui.sumber