最近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) import React, { useState } from "react";
import Child from "./Child";
import "./styles.css";
export default function App() {
let [state, setState] = useState({
value: ""
});
let handleChange = input => {
setState(prevValue => {
return { value: input };
});
console.log(state.value);
};
return (
<div className="App">
<h1>{state.value}</h1>
<Child handleChange={handleChange} value={state.value} />
</div>
);
}
import React from "react";
function Child(props) {
return (
<input
type="text"
placeholder="type..."
onChange={e => {
let newValue = e.target.value;
props.handleChange(newValue);
}}
value={props.value}
/>
);
} …Run Code Online (Sandbox Code Playgroud) 我有一个带有下拉菜单的表单,当我选择下拉菜单时,我将值推送到查询字符串上。当第一次点击带有该查询字符串的 url 时,它将查询字符串参数存储到状态中,然后使用它来填充下拉列表。这一切都按预期进行。我的问题是触发表单以查看查询字符串的更改,同时仍在同一页面上。
如果我已经在页面上,但然后单击反应路由器链接到同一页面但使用不同的查询字符串参数,它不会捕获/看到它已更改。我想知道如何观察查询字符串的变化,或者是否有更好的方法来处理这个问题。
我发现你可以监听 React-Router 在后台使用的历史对象,但我在这方面没有取得什么成功,而且我再次不确定这是否是正确的方法https:// /github.com/ReactTraining/history/blob/master/docs/getting-started.md
我尝试将以下内容添加到页面中,但当我更改 url 的查询字符串(也称为搜索)时,侦听器似乎从未触发。想知道我错过了什么吗?
useEffect(() => {
// Listen for changes to the current location.
console.info("wiring up history listener");
let unlisten = history.listen(({ location, action }) => {
console.info("HISTORY CHANGED", location.search);
console.log(action, location.pathname, location.state);
// Plan was to update my state here if needed
});
return unlisten;
}, []);
Run Code Online (Sandbox Code Playgroud)
使用react-router-domv6。
TypeError: Cannot read properties of undefined (reading 'params')
5 | import products from '../products'
6 |
7 | function ProductScreen({ match }) {
8 | const product = products.find((p) => p._id == match.params.id)
9 | return (
10 | <div>
11 | {product.name}
Run Code Online (Sandbox Code Playgroud)
这是我的 ProductScreen.js 文件,导致出现问题
import React from 'react'
import { Link } from 'react-router-dom'
import { Row, Col, Image, ListGroup, Button, Card } from 'react-bootstrap'
import Rating from '../components/Rating' …Run Code Online (Sandbox Code Playgroud) 我有一个应用程序,有时会加载查询字符串 param t。
一开始,我希望应用程序读取此参数(如果可用)并将其从 URL 中删除。
在根组件上,我正在这样做:
const [searchParams, setSearchParams] = useSearchParams();
if (searchParams.has('t')) {
const token = searchParams.get('t');
if (token) {
searchParams.delete('t');
const newParams: {[key: string]: string} = {};
searchParams.forEach((value: string, key: string) => {
newParams[key] = value;
});
console.log('setting params: ');
console.dir(newParams);
setSearchParams(newParams);
AuthController.setAccessToken(token);
}
}
Run Code Online (Sandbox Code Playgroud)
我看到它正确读取 paramt并且 newParams 对象为空或仅包含其他参数,但由于某种原因setSearchParams(newParams)似乎没有执行任何操作。参数t仍然在 URL 中。
我怎样才能让它从 URL 中删除这个参数?
我正在尝试为其父路由中的一个子路由创建索引路由,但我不断收到错误消息,提示类型“true”不可分配给类型“false |” 不明确的'。我如何解决它?
<Routes>
<Route path="/" element={<Profile />}>
<Route index path="/username" element={<ProfileDetails />} />
<Route path="settings/profile" element={<EditProfile />} />
</Route>
<Route path="/login" element={<Login />} />
<Route path="/register" element={<SignUp />} />
</Routes>
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) 假设我有这个简单的虚拟组件:
const Component = () => {
const [state, setState] = useState(1);
setState(1);
return <div>Component</div>
}
Run Code Online (Sandbox Code Playgroud)
在此代码中,我直接在组件主体中将状态更新为与之前相同的值。但是,即使值保持不变,这也会导致过多的重新渲染。
据我所知,在 中React.useState,如果状态值更新为与之前相同的值 - React 不会重新渲染组件。那么为什么会发生在这里呢?
但是useEffect,如果我尝试在组件主体中而不是直接在组件主体中执行类似的操作:
const Component = () => {
const [state, setState] = useState(1);
useEffect(() => {
setState(1);
}, [state])
return <div>Component</div>
}
Run Code Online (Sandbox Code Playgroud)
这不会导致任何无限循环,并且完全符合如果状态保持不变,React 不会重新渲染组件的规则。
所以我的问题是:为什么当我直接在组件主体中执行此操作时会导致无限循环,而在组件主体中却useEffect不会?
有人对此有一些“幕后”解释吗?
在版本 5 中,我可以通过这种方式执行检查https://v5.reactrouter.com/web/api/matchPath
import { matchPath } from "react-router";
const match = matchPath("/users/123", {
path: "/users/:id",
exact: true,
strict: false
});
Run Code Online (Sandbox Code Playgroud)
在版本 6 中,我在屏幕上看到错误。现在应该如何运作? 错误:pathname.match 不是函数
我正在尝试遵循 MUI 的Mini 变体抽屉中给出的示例,使左侧ListItemButton能够与 React Router v6 的 Link 元素一起使用。该文档对于如何使用路由器库实现这一目标不是很清楚。我尝试了几种变体但无法使其工作。MUI 的 CodeSandBox 链接位于此处。有人可以告诉我如何启用ListItemButton像这样的路径/my-path吗?
reactjs ×9
react-router ×6
javascript ×3
rtk-query ×2
components ×1
material-ui ×1
react-hooks ×1
state ×1
typescript ×1