如何取消订阅 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 查询,它将替换 createAsyncThunk
:https://redux-toolkit.js.org/tutorials/rtk-query
根据我们的discussion编辑:
useEffect(() => {
dispatch(fetchSingleMediaTitle(id));
}, [dispatch, id]);
我可以加载我的数据,但只能在刷新页面后加载。在此之前,它会显示我单击的上一个项目的数据。它的行为就像缓存一样。
这是我的 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 查询,它将替换 createAsyncThunk
:https://redux-toolkit.js.org/tutorials/rtk-query
根据我们的discussion编辑:
useEffect(() => {
dispatch(fetchSingleMediaTitle(id));
}, [dispatch, id]);