所选图书取决于useParams挂钩返回的URL参数.除非useParams挂钩返回的值已更改,否则也不应从渲染到渲染重新定义选定的图书.

我想知道useParams是否返回一个从渲染到渲染的持久对象.

const { books, setBooks } = useContext(BooksContext);
const { bookId = 0 } = useParams();

const selectedBook = useMemo(
  () => books.find(book => book.id === +bookId) || null,
  [books, bookId],
);

推荐答案

我想知道useParams是否从 渲染以进行渲染.

简而言之,不是,它在每个渲染周期返回一个新的对象引用.如果您愿意的话,测试这一点很简单:

Edit does-the-useparams-hook-return-a-persistent-object-from-render-to-render

const params = useParams();
const { bookId = 0 } = useParams();

useEffect(() => {
  console.log("Effect 1, params updated", { params });
}, [params]);

useEffect(() => {
  console.log("Effect 2, bookId updated", { bookId });
}, [bookId]);

由于React.StrictMode组件的原因,忽略了最初的双重安装,每次点击"重现"按钮都会触发第一次效果,而不是第二次效果.

100路由路径参数为字符串类型,且字符串101等于其自身,102为不同的引用.

const a = "foo";
const b = a;
const c = "foo";

console.log(a === b); // true
console.log(a === c); // true
console.log(b === c); // true

这对您的代码意味着bookId,无论它是different字符串引用,在被用作useMemo挂钩的依赖值方面都无关紧要.只要bookId的第104位保持不变,就不会触发对所选图书的重新计算.因为路由路径参数始终是字符串,所以我建议将您要比较的值转换为字符串,因此代码使用类型安全的比较105涵盖类似数字的字符串和字母数字id值,而不是将bookId值强制为数字类型.

const { books, setBooks } = useContext(BooksContext);
const { bookId = 0 } = useParams();

const selectedBook = useMemo(
  () => books.find(book => String(book.id) === bookId) || null,
  [books, bookId],
);

Javascript相关问答推荐

React Native平面列表自动滚动

我试图实现用户验证的reduxstore 和操作中出了什么问题?

被CSS优先级所迷惑

Promise Chain中的第二个useState不更新

Angular 订阅部分相互依赖并返回数组多个异步Http调用

material UI按钮组样式props 不反射

在运行时使用Next JS App Router在服务器组件中运行自定义函数

Eval vs函数()返回语义

NG/Express API路由处理程序停止工作

MarkLogic-earch.suggest不返回任何值

将多个文本框中的输出合并到一个文本框中

当我点击一个按钮后按回车键时,如何阻止它再次被点击

在Java脚本中构建接口的对象

在高位图中显示每个y轴系列的多个值

Chrome上的印度时区名S有问题吗?

如何检测当前是否没有按下键盘上的键?

如何在加载页面时使锚定标记成为焦点

material UI自动完成全宽

验证Java脚本函数中的两个变量

如何在函数组件中保留对计时器的引用