我想知道useParams
是否从
渲染以进行渲染.
简而言之,不是,它在每个渲染周期返回一个新的对象引用.如果您愿意的话,测试这一点很简单:
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],
);