如何取消订阅 dispatch 以在 useEffect 上加载新数据? - 我正在使用 Redux 工具包

How do I unsubscribe to the dispatch to grab new data onload on useEffect? - I'm using Redux Toolkit

我可以加载我的数据,但只能在刷新页面后加载。在此之前,它会显示我单击的上一个项目的数据。它的行为就像缓存一样。

这是我的 mediaSlice

import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

const KEY = process.env.REACT_APP_API_KEY
const BASE_URL = process.env.REACT_APP_BASE_URL
const HBO_SINGLE_MEDIA_API = `${BASE_URL}/titlestest`

const initialState = {
  media:{},
  status: 'idle',  //'idle', 'loading', 'succeeded', 'failed'  
  error:null
}

export const fetchSingleMediaTitle = createAsyncThunk(
  'media/fetchSingleMediaTitle', 
  async (id) => { 
    const response = await axios.get(
      HBO_SINGLE_MEDIA_API,
      {
        headers: {
          'Content-Type': 'application/json',
          'X-API-KEY': KEY,
        },
        params: {
          titleId: id,
        }
      }
    )

    return response.data.Item;
  } 
)

const mediaSlice = createSlice({
  name: 'media',
  initialState,
  reducers:{},
  extraReducers: {
    [fetchSingleMediaTitle.pending]: () => {
      console.log("Pending");
    },
    [fetchSingleMediaTitle.fulfilled]: (state, { payload }) => {
      state.status = 'succeeded'
      state.media = payload
    },
    [fetchSingleMediaTitle.rejected]: () => {
      console.log("Rejected");
    },
  }
})

// SELECTORS
export const selectSingleMedia = (state) => state.media.media;

export const getMediaStatus = (state) => state.media.status;

export default mediaSlice.reducer

然后媒体组件具有您所期望的

const [media, setMedia] = useState([]);   
const {id} = useParams();
const dispatch = useDispatch();

const singlemedia = useSelector((state) => selectSingleMedia(state, id))
const mediaStatus = useSelector(getMediaStatus)

useEffect(() => { 
  if (mediaStatus === 'idle') {
    dispatch(fetchSingleMediaTitle(id)) //yes, it's imported
  }
    
  setMedia(singlemedia); 

  //it returns the array with the data but not the current one
  console.log("singlemedia: ", singlemedia); 

  return () => {  };
  // Someone suggested removing the dependencies below but then it doesn't load anything.
}, [id, singlemedia, mediaStatus, dispatch, media_data])

我在这里不知所措,因为据我了解,useEffect 应该触发 onload 并为我提供当前数据。参数中的 ID 正确,但状态未发生变化。

提前致谢

编辑 作为参考,这里是控制台日志。这些控制台日志在 useEffect 中。 API 比 useEffect 稍慢,并且渲染发生在数据准备好之前(竞争条件),或者至少我认为这是在这里发生的,这就是它加载空然后再次加载的原因。但令人困惑的是,所有这些都只发生在页面刷新时。在正常加载时,状态不为空被加载,并且 UI 及时渲染它(无竞争条件),只是,它加载了来自先前状态形状

的旧数据

这是 redux 开发工具

问题很简单,去掉媒体内部状态变量即可:

const [media, setMedia] = useState([]); 

因为您现在正在做的是在这里发送异步请求:

if (mediaStatus === 'idle') {
    dispatch(fetchSingleMediaTitle(id)) //yes, it's imported
  }

在后端响应之前,您读取存储并将其设置为内部状态:

setMedia(singlemedia); // This is old data now, as we are waiting for the backend

如果您希望显示商店状态,只需在渲染方法中使用 singlemedia。

如果您希望再次使用一些模拟后端响应的临时状态,请使用 singlemedia 并在 redux 存储中实现临时状态。

PS。 useEffect 应该只依赖于 id 和 useDispatch

您的选择器接受一个参数,但您传递了两个参数。将其更改为:

const singlemedia = useSelector(selectSingleMedia);

第二,你的singlemedia是国家。没必要 setMedia(singlemedia);.

您的 useEffect 应如下所示:

useEffect(() => { 
  if (mediaStatus === 'idle') {
    dispatch(fetchSingleMediaTitle(id));
  }
}, [dispatch, id, mediaStatus]);

此外,您应该查看 RTK 查询,它将替换 createAsyncThunkhttps://redux-toolkit.js.org/tutorials/rtk-query

根据我们的discussion编辑:

useEffect(() => { 
  dispatch(fetchSingleMediaTitle(id));
}, [dispatch, id]);