如何解决导航到另一页时,next / link丢失状态
我正在开发库 Next.js应用程序。出于这个问题的目的,我在应用程序中有两个页面: BooksPage (列出所有书籍)和 BookPage (用于呈现书籍的详细信息)。在组件方面,我有一个<Books />
组件,它为我的图书馆数据库中的每本书提供了一个<Book />
组件。
这是我的组成部分:
Books.js :
function Books({ books }) {
return (
<>
{books.map(book => (
<Book key={book.id} book={book} />
))}
</>
);
}
Book.js :
class Book extends React.Component {
constructor(props,context) {
super(props,context);
this.state = { liked: false };
}
like = () => {
this.setState({ liked: this.state.liked ? false : true })
};
render() {
return (
<>
<Link href={`/books/${book.slug}`}>
<a>{book.title}</a>
</Link>
<Button onClick={this.like}>
<LikeIcon
className={this.state.liked ? "text-success" : "text-dark"}
/>
</Button>
</>
);
}
}
问题:
说我在 BooksPage 页面上。当我单击<Book />
的“赞”按钮时,图标颜色在前端正确切换,并且在后端成功添加或删除了类似颜色。当我刷新 BooksPage 时,所有状态都保持不变。
当我喜欢 BooksPage 上的内容,然后立即导航到 BookPage 而不使用next / link刷新时,就会出现问题。那里的“赞”按钮未始终切换,并且 BooksPage 的状态丢失。请注意,如果我硬刷新页面,一切都会恢复正常。
慢速解决方案:请勿使用next / link。
替换
<Link href={`/books/${book.slug}`}>
<a>{book.title}</a>
</Link>
使用
<a href={`/books/${book.slug}`}>{book.title}</a>
快速解决方案:继续使用下一个/链接吗?
导航到另一条预渲染的路线时,是否可以使用next / link并保持状态?
解决方法
您需要使用Model.refresh_from_db(...)
--(Django Doc)方法来 从数据库中检索更新的值
class DeleteLikeView(APIView):
def post(self,request,book):
book = get_object_or_404(Book,id=book)
print(book.num_of_likes)
like = Like.objects.get(user=request.user,book=book)
like.delete()
book.refresh_from_db() # here is the update
print(book.num_of_likes) # You will get the updated value
return ...
,
TLDR:每当需要更改按钮时,API都必须更改数据,并且必须更新最接近父级的本地状态以更新button
的外观。 API将控制本地状态的各个方面。除非API请求成功,否则您无法更新本地状态。因此,客户端和API始终为1:1。
Book.js 中的Button
组件应不与API数据分开维护其自身状态;相反,无论您从API那里获取book
数据,它也应该控制按钮的状态(及其外观)。为什么?因为使用当前方法,API请求可能会失败,但是客户端仍将更新。结果,API和客户端可能不再是1:1(客户端显示喜欢,但API仍然显示不喜欢/不喜欢)。
在实践中,您将有一个充当状态管理器的父容器。它获取所有相关数据,处理数据更新,并使用 stateless 子组件显示结果。每当需要更新子组件时(例如,通过按下按钮显示“喜欢”或“不喜欢”按钮),它都必须首先发出API请求以更改数据,然后API必须以相关数据响应更新孩子使用的状态:
或者,如果该组件是可重用的,那么您将有条件地使用this.props.book
(来自父容器)来呈现它,或者子组件必须从API请求数据以更新其自身的本地{{1 }}。与上图相同,API请求控制状态更改的所有方面:
还有另一种与上图相同的方法,但是它使用子级本地状态,而不管父级状态如何。此子状态将仅通过其自己的类方法进行更新。这带来了更多的复杂性,因为您必须确保任何父状态更改不会用陈旧的数据重新呈现子组件。最终,哪种方法取决于您。
附带说明:由于 库 不会呈现页面,也不会尝试内部页面导航。相反,它们提供了可重复使用的组件,这些组件可以被一个或多个NextJS项目页面或组件使用。
,以某种方式通过API传递书籍的liked
属性。然后,将该道具从Books
组件传递到Book
组件。
向您的图书组件添加componentDidUpdate()
方法。
class Book extends React.Component {
constructor(props,context) {
super(props,context);
this.state = { liked: this.props.liked };
}
componentDidUpdate(prevProps) {
if (this.props.liked !== prevProps.liked) {
this.setState({
liked: this.props.liked,});
}
}
like = () => {
this.setState({ liked: !this.state.liked })
};
render() {
return (
<>
<Link href={`/books/${book.slug}`}>
<a>{book.title}</a>
</Link>
<Button onClick={this.like}>
<LikeIcon
className={this.state.liked ? "text-success" : "text-dark"}
/>
</Button>
</>
);
}
}
,
在DeleteLikeView类中,您获得书本对象。它从数据库检索并保存在book变量中。 当您删除类似对象的对象时,数据库中的num_of_likes属性已更新,但您的变量仍包含先前的对象。在like.delete()命令之后,您应该再次获取对象并打印num_of_likes att。符合您的预期。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。