Deskripsi

Saya memiliki komponen yang menunjukkan data yang didapat dari server dan menampilkannya di atas tabel menggunakan status, tableData dan harus disetel ketika tindakan Redux dikirim.

Saya telah menggunakan pustaka pendengar tindakan yang menggunakan Redux middleware yang terdiri dari 63 baris kode. redux-listeners-qkreltms.

Misalnya ketika saya mendaftarkan fungsi pada analysisListIsReady({}).type yaitu ANALYSISLIST_IS_READY maka ketika tindakan tersebut dikirim, fungsi tersebut dipanggil.

Isu

Masalahnya adalah reaksi terkadang memunculkan kesalahan: Can't update react state... for setTableData sehingga data respons diabaikan untuk disetel. Saya ingin mencari tahu ketika itu terjadi.

Saya berasumsi bahwa itu karena pelepasan komponen, jadi saya mencetak beberapa log, tetapi tidak ada log yang dicetak dan juga ComponentA tidak hilang.

Tidak ada kesalahan ketika saya menghapus getAnalysisJsonPathApi dan getResource, jadi saya mencoba untuk mengulanginya, tetapi gagal... tautan

Tidak ada kesalahan saat saya menghapus listenMiddleware.addListener lihat: #2

#1

// ComponentA
const [tableData, setTableData] = useState([])
useEffect(() => {
  return () => {
    console.log("unmounted1")
}}, [])  

useEffect(() => {
    listenMiddleware.addListener(analysisListIsReady({}).type, (_) => {
      try {
        getAnalysisJsonPathApi().then((res) => {
          //...
          getResource(volumeUrl)
            .then((data: any) => {
              // ...
              setTableData(data)
            })
        })
      } catch (error) {
        warn(error.message)
      }
    })

    return () => {
      console.log("unmounted2")
    }
  }, [])
export const getAnalysisJsonPathApi = () => {
  return api
    .post('/segment/volume')
    .then(({ data }) => data)

export const getResource = async (src: string, isImage?: boolean): Promise<ArrayBuffer> =>
  api
    .get(src)
    .then(({ data }) => data)

#2

// ComponentA
const [tableData, setTableData] = useState([])
useEffect(() => {
  return () => {
    console.log("unmounted1")
}}, [])  

useEffect(() => {
    if (steps.step2a) {
      try {
        getAnalysisJsonPathApi().then((res) => {
          //...
          getResource(volumeUrl)
            .then((data: any) => {
              // ...
              setTableData(data)
            })
        })
      } catch (error) {
        warn(error.message)
      }
    }

    return () => {
      console.log("unmounted2")
    }
  }, [steps.step2a])
1
JillAndMe 14 Desember 2020, 13:24

3 jawaban

Jawaban Terbaik

Saya menemukan itu karena redux-listeners-qkreltms, middleware Redux.

Itu tetap berfungsi ketika komponen dipasang ke pendengar, tetapi tidak pernah mengubah fungsinya bahkan komponen dilepas.

  middleware.addListener = (type, listener) => {
    for (let i = 0; i < listeners.length; i += 1) {
      if (listeners[i].type === type) {
        return;
      }
    }
    listeners.push(createListener(type, listener));
  };
0
JillAndMe 15 Desember 2020, 06:22

Nah, seperti yang Anda katakan:

karena melepas komponen

Dalam fungsi UseEffect() Anda, Anda perlu memeriksa apakah componenet sudah terpasang atau tidak, dengan kata lain, Anda perlu melakukan logika componentDidMount & componentDidUpdate (jika diperlukan):

const mounted = useRef();

useEffect(() => {
if (!mounted.current) {
    // do componentDidMount logic
    console.log('componentDidMount');
    mounted.current = true;
} else {
    // do componentDidUpdate logic
    console.log('componentDidUpdate');
}
});
1
Ahmad MOUSSA 14 Desember 2020, 10:44

Saya tidak pergi ke detail kode pertanyaan Anda, tetapi petunjuk saya mungkin membantu Anda, biasanya kesalahan ini terjadi pada fungsi fetchData, misalkan Anda memiliki fungsi fetchData seperti di bawah ini:

fetchData(){
...
let call = await service.getData();
...
--->setState(newItems)//Here
}

Jadi ketika panggilan api berakhir dan status ingin diperbarui, jika komponen telah dilepas, tidak ada status yang harus disetel, Anda dapat menggunakan variabel bool dan menyetelnya salah saat komponen akan dilepas:

    let stillActive= true;
    
    fetchData(){
    active = true;
    ...
    let call = await service.getData();
    ...
    if(stillActive)
       setState(newItems)//Here
    }
    }

    componentWillUnmount(){
        active = false;
    }
1
Dharman 14 Desember 2020, 10:55