Django+React全栈开发:文章详情
验证问题
修改ArticleDetail
组件,从后端拿到文章正文。现在如果直接启动应用,会发现获取文章列表时后端返回了403响应,因为在上一节中设置了身份验证,每次请求必须携带正确的JWT,但是事实上对于文章列表和详情的GET
请求完全可以忽略验证,毕竟这是一个博客应用,现在先处理这个问题。
这里有一个简陋的解决办法,改写上一章编写的jwt_auth/authentication.py
:
如果请求头不包含token则直接返回None,接下来由定义在视图类中的permissions
类处理请求,我们之前设置的是IsAdminOrReadonly
,未登录用户将拥有只读权限。这个办法有些粗糙,读者可以尝试改进。
Hooks
前端获取文章详情和文章列表组件中请求文章列表的方式差不多。但是文章列表组件是一个类组件,API请求是在类组件的componentDidMount
这个生命周期里完成的。ArticleDetail
是一个函数组件,前面提到过,函数组件是无状态的,没有生命周期, 那么是否要把函数组件改成类组件呢?
React16为函数式组件提供了一个名为Hook的新特性,官方介绍是这样的:
Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class.
Hook以函数的形式让函数组件获得类组件的state和生命周期功能。这次要用到两个Hook,分别是useState
和useEffect
,下面先看看useState
:
增加了两行代码,useState
的参数用来设置state的默认值,返回值是一个列表,第一个元素是创建的state,第二个元素是一个函数,可以用来修改state。目前这个state还没有被用上,现在来写一个简单的交互功能,添加一个按钮,点击一下将页面正文内容变成hello world:
这里用到了React的合成事件onClick
,当按钮被点击时,就会触发回调函数,回调函数使用了Hook返回的setBody
函数,将body的值更改为「Hello world」。可以回顾一下类组件,上面的代码其实等价于下面这个类组件:
相比之下,是不是感觉函数式的写法更简洁呢?
那么,怎么做到和ArticleList
组件componentDidMount
生命周期相同的功能呢?这就需要用到另一个Hook:useEffect
。
稍微给正文加点样式方便区分,注意useEffect函数的两个参数,第一个参数是一个回调函数,通过GET请求获取后端的文章详情,这里用到了从路由参数获得的articleId
来拼接字符串得到所需文章的后端地址,序列化响应后通过setBody设置body的值;第二个参数是一个列表,useEffect会监视列表中的值,当值发生变化时将会重新执行回调函数更新组件,如果这个列表设置为空将会只执行一次就结束。
注意事项
使用Hook有一些注意事项:
- Hooks只能出现在函数式组件或自定义Hook中
- Hooks必须在最顶层(不能在条件语句、循环体或者嵌套函数内部)
如果有时候你想在某个条件下才执行useEffect
的内容,那么不要把整个Hook放到条件语句内,而是在useEffect
的回调函数内部做条件判断。
开发者可以自定义Hook来复用代码,例如多个组件都需要一个获取用户信息的逻辑,那么就可以封装一个自定义Hook:
一般约定这类自定义Hook函数以use
开发,回顾之前的代码,可以发现,其实我们早就已经用到了一个Hook函数:useParams
。
练习
读者可以尝试在页面上呈现文章标题创建日期等其他信息。