我认为我缺少有关 Redux 和 RTK 查询工具的一些东西。我还为此使用 RTK Query OpenAPI codegen。
现在我有一个如下所示的 API ->
export const api = generatedApi.enhanceEndpoints({
endpoints: {
getMaterials: {
transformResponse: response => normalize(response),
},
},
})
Run Code Online (Sandbox Code Playgroud)
这在我的组件中很好地返回了标准化数据:
const Materials = () => {
const { data, isLoading, error } = useGetMaterialsQuery()
/*
Cool this gives me data back like:
{
[id]: {
id,
prop1: 'blah',
prop2: 'blah2'
}
}
*/
console.log(data)
// but now I want to structure this data differently using selector
const newDataStructure = useSelector(addSomeMetaDataAndStructureDifferentlySelector)
return …Run Code Online (Sandbox Code Playgroud) 我使用 redux 工具包创建 API 问题很短:如何动态更改 API 中的 baseUrl?详细问题:这里是 createApi 方法 一个对象被传递给这个方法,其中一个键是“baseQuery”
export const WebApi = createApi({
reducerPath: 'API',
baseQuery: fetchBaseQuery({ baseUrl: 'http://localhost:3001/api' }),
endpoints: () => ({}),
});
Run Code Online (Sandbox Code Playgroud)
那么问题来了,如何动态改变baseUrl呢?它在商店里,但我不能把它放在这里。我尝试了自定义查询文档中的解决方案 https://redux-toolkit.js.org/rtk-query/usage/customizing-queries#constructing-a-dynamic-base-url-using-redux-state
但它不允许精确更改baseUrl,只能动态处理请求本身,该请求已经在baseUrl之后
那么,如何在createApi方法中获取和更改baseUrl呢?
最近react-router发布了新的 6.4,它能够在组件渲染之前加载数据。(https://reactrouter.com/en/main/start/overview#data-loading)
这看起来是一个很酷的功能。我想将它与 RTK 查询一起使用,因为我已经使用 Redux Toolkit。
所以我想做一件基本的事情,我有 api 来加载帖子。我想加载它们,如果请求失败 - 重定向到其他页面。在react-router6.4 中,这一切都可以在路由器中完成(https://reactrouter.com/en/main/start/overview#redirects)。
路由器超出了react的范围,所以我不能使用rtk查询提供的钩子,所以这意味着我必须使用没有钩子的rtk查询,根据文档这是完全可能的(https://redux-toolkit.router)。 js.org/rtk-query/usage/usage-without-react-hooks)
所以我的问题是,如何读取react-router加载器中请求的状态。我可以使用钩子读取组件中的状态,但这会使组件变得“脏”并将逻辑分散到整个应用程序中。
import React from "react";
import ReactDOM from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import { Provider } from "react-redux";
import { store } from "./redux/redux";
import { Comments } from "./Comments";
import { Posts } from "./Posts";
import { Root } from "./Root";
import { postsApi } from "./redux/redux";
const …Run Code Online (Sandbox Code Playgroud) 我是 RTK 查询的新手,正在努力解决必须实现的用例。
场景:我必须合并两个 API 调用的结果:第一个 API 调用是私有 API 调用,而第二个 API 调用是公共 API 调用。我需要合并这两个 API 的响应,并将计算结果写入 RTK 缓存,以便 UI 可以相应更新。
问题:我发现一旦调用await queryFullfilled,RTK 查询就会立即将来自该 API 调用的响应写入其缓存,然后当我进行计算并尝试使用缓存更新 RTK 缓存时,缓存apiSlice.util.updateQueryData将再次更改。这意味着 UI 将渲染两次,第一次使用错误的值(人员数组),第二次使用正确的值(由 id 和实体组成的 JSON)。
问题:有没有办法只向 RTK 缓存写入 1 次,这样我就可以得到我需要的计算值?array因为发生的情况是,在某些情况下,我需要JSON才能进入缓存{ids: [...], entities: {}}。
import { createEntityAdapter } from '@reduxjs/toolkit';
import axios from 'axios';
export const personsAdapter = createEntityAdapter();
const permitsInitialState = personsAdapter.getInitialState();
export const apiSlice = myServiceApi.injectEndpoints({
endpoints: (builder) => ({
getPersons: …Run Code Online (Sandbox Code Playgroud) 我正在尝试使用 RTK 查询突变将文件上传到 API。这是我的突变代码:
addBanner: builder.mutation({
query(body) {
return {
url: `/api/banners`,
method: 'POST',
body,
}
},
})
Run Code Online (Sandbox Code Playgroud)
这是我生成请求数据的方法。
const [addBanner, { isBannerLoading }] = useAddBannerMutation();
Run Code Online (Sandbox Code Playgroud)
const new_banner = new FormData();
new_banner.append("file", my_file);
new_banner.append("type", my_type);
new_banner.append("title", my_title);
addBanner(new_banner).unwrap().then( () => ...
Run Code Online (Sandbox Code Playgroud)
但我收到一个错误:
A non-serializable value was detected in the state, in the path: `api.mutations.L-Mje7bYDfyNCC4NcxFD3.originalArgs.file`...
Run Code Online (Sandbox Code Playgroud)
我知道我可以通过中间件完全禁用不可序列化检查,但我认为这不是使用 Redux Toolkit 和 RTK 的合适方法。没有文件一切正常。RTK上传文件有什么正确的方法吗?
我正在尝试构建一个拦截器,以应对 RTK 查询访问令牌无效的情况。我已经通过文档中的示例构建了它,如下所示:
const baseQuery = fetchBaseQuery({
baseUrl: BASE_URL,
prepareHeaders: (headers, { getState }) => {
const {
auth: {
user: { accessToken },
},
} = getState() as RootState;
if (accessToken) {
headers.set('authorization', `Bearer ${accessToken}`);
}
return headers;
},
});
const baseQueryWithReauth: BaseQueryFn<string | FetchArgs, unknown, FetchBaseQueryError> = async (
args,
api,
extraOptions
) => {
let result = await baseQuery(args, api, extraOptions);
if (result.error && result.error.status === 401) {
const refreshResult = await baseQuery('token/refresh/', api, extraOptions);
if (refreshResult.data) …Run Code Online (Sandbox Code Playgroud) 我刚开始使用 RTK 查询,但遇到问题
我的应用程序在一个大 JSON 中包含所有设置,因此我创建一个 RTK 查询来获取设置。在教程中,示例是关于useQuery在组件中使用钩子并立即显示结果,但由于设置太大,因此需要多个页面/组件来显示它并允许用户更改设置
因为需要更改设置,所以我认为将状态放入商店是一个好主意,我的问题是如何将API结果放入商店?
我可以看到一些围绕它的方法
useQuery在组件中使用,当它产生时,然后进行调度以将数据放入存储中
从 API 中放入useQuery所有组件都使用它并使用它来获取缓存数据,那么就不需要将其放在存储上并使用组件状态来设置更改(我不确定这种方法,因为有很多设置 - 即使分为不同的页面,使用组件状态来管理它似乎也不正确)
我是 RTK 和 RTK 查询的新手,只是想知道最好/好的方法是什么?
我正在创建一个反应本机应用程序,并且收到此警告。位于reducerPath“api”的 RTK-Query API 的中间件尚未添加到商店中。自动缓存收集、自动重新获取等功能将不可用。
我看到我的 api 没有被重新获取。
这是我的 rootReducer.ts 文件
import {combineReducers} from '@reduxjs/toolkit';
import { storiesApi } from 'src/services/storiesService'
const appReducer = combineReducers({
[storiesApi.reducerPath]: storiesApi.reducer,
});
const rootReducer = (state, action) => {
if (action.type === 'RESET_APP') {
state = undefined;
}
return appReducer(state, action);
};
export const resetAppAction = () => dispatch => {
console.log('Reset Redux Store');
dispatch({type: 'RESET_APP'});
};
export default rootReducer;
Run Code Online (Sandbox Code Playgroud)
这是我的 store.ts 文件
import { useDispatch as useReduxDispatch, useSelector as useReduxSelector } from 'react-redux';
import …Run Code Online (Sandbox Code Playgroud) 我试过了
有什么办法可以使用await来处理普通的get请求吗?
相关问题:
具体来说,我想做以下事情:
useEffect(() => {
someRTKQuerysGetMethod()
.then(data => setValuesToForm(data))
}, [])
Run Code Online (Sandbox Code Playgroud)
不过,我从 phry 收到的评论可能已经解决了问题。
const [getPokemon] = useLazyGetPokemonQuery()
useEffect(() => {
getPokemon({...})
.unwrap()
.then(data => setValuesToForm(data))
}, [])
Run Code Online (Sandbox Code Playgroud)
非常感谢...!!
我是 RTK 查询的新手,在使用不同参数的查询之间共享数据时遇到问题。
// api.js
const { useGetStuffQuery } = api.injectEndpoints({
endpoints: (builder) => ({
getStuff: builder.query({
query: (stuffId) => ({ url: `http://some.random-url.com/${stuffId}` }),
}),
}),
});
// component.js
function(props) {
const [id, setId] = useState(1);
const { data, isLoading } = useGetStuffQuery(id);
if (val === '2') {
console.log('datttt', data); // this initially prints data from id:1
}
return <div>
<input value={id} onChange={(e) => setId(e.target.value)} />
{
isLoading ? <span>loading...</span>
: <span>data is: {data}</span>
}
</div>
}
Run Code Online (Sandbox Code Playgroud)
当我将 id 从 …
rtk-query ×10
reactjs ×5
redux ×4
react-redux ×2
file-upload ×1
react-native ×1
react-router ×1