使用 SWR 条件获取和 react-bootstrap 手风琴
useSWR conditional fetch and react-boostrap Accordion
尝试将 youtube 评论加载到无限加载组件中(为此使用 npm)
由于无限加载组件是父 Accordion 组件的子组件(来自 react-bootstrap)以及我正在尝试的,所以发生了混乱仅当 Accordion 被点击(打开)时,achieve 才使用 useSWR 获取。
我尝试的是使用 useSWR 条件,以便仅在状态“show”为真时获取,这是在函数内部设置的:
const showComments = () => {
setShow(true)
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
}
调用了 Accordion.Toggle onClick 事件。
但是我点了两次手风琴之后才显示评论,这是为什么?
我的代码是:
import { useState, useEffect } from 'react'
import { Row, Col, Button, Accordion } from 'react-bootstrap'
import * as _ from 'lodash'
import useSWR from 'swr'
import { MdUnfoldMore } from 'react-icons/md'
import InfiniteScroll from "react-infinite-scroll-component"
import Comments from './Comments'
const siteurl = process.env.NEXT_PUBLIC_SITE_URL
export default function VideoComments({ video }){
const [show, setShow] = useState(false)
const [counter, setCounter] = useState(0)
const [commList, setCommList] = useState(null)
const [commChunks, setCommChunks] = useState([])
const showComments = () => {
setShow(true)
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
}
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data: comments, error } = useSWR(show ? `${siteurl}/api/c/${video.id}` : null, fetcher)
// useEffect(() => {
// if (comments) {
// commChunks = _.chunk(comments.comm, 10)
// setCommList(commChunks[counter])
// }
// },[comments])
const fetchMoreData = () => {
const newCounter = counter + 1;
// loaded all, return
if (commChunks[newCounter] === undefined || commChunks[newCounter] == null) {
return;
}
const newCommList = [
...commList,
...commChunks[newCounter]
]
setCommList(newCommList)
setCounter(newCounter)
}
return (
<div>
<Accordion>
<Row>
<Col xs={12}>
<Accordion.Toggle as={Button} onClick={() => {showComments()}} variant="link" eventKey="0"><div><span>Comments</span></div></Accordion.Toggle>
</Col>
</Row>
<Accordion.Collapse eventKey="0">
<div id="commentsBox" style={{maxHeight: '300px', overflowY: 'auto'}}>
<Col xs={12}>
{commList &&
<InfiniteScroll
dataLength={commList.length}
next={fetchMoreData}
hasMore={true}
scrollableTarget="commentsBox"
>
<Comments data={commList} />
</InfiniteScroll>
}
</Col>
</div>
</Accordion.Collapse>
</Accordion>
</div>
);
}
编辑:按照下面的建议,我重新激活了useEffect,但它仍然需要点击两次手风琴
const showComments = () => {
setShow(true)
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
}
const { data: comments } = useSWR(show ? `${siteurl}/api/c/${video.id}` : null, fetcher)
useEffect(() => {
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
},[comments])
您评论了处理评论的 useEffect
:
// useEffect(() => {
// if (comments) {
// commChunks = _.chunk(comments.comm, 10)
// setCommList(commChunks[counter])
// }
// },[comments])
发生了什么:
- 您点击手风琴,
showComments
被调用
show
设置为真,但是因为comments
未定义,所以commList
和commChunks
没有设置
- 组件重新渲染,现在
useSWR
可以使用url获取数据
- 组件在获取 si 完成后重新呈现,现在
comments
包含数据
- 您第二次点击手风琴,
showComments
被调用
show
设置为true,这次设置commList
和commChunks
- 组件重新呈现
InfiniteScroll
和 Comments
问题出在您的 useEffect
中,在修改 commChunks
状态后立即调用 setCommList(commChunks[counter])
不会有更新的值。在 React 中设置状态是一个异步操作(参见 )。
您应该将注释保存在块范围变量中,并使用它来连续更新两种状态。
useEffect(() => {
if (comments) {
const commentsChunks = _.chunk(comments.comm, 10)
setCommChunks(commentsChunks)
setCommList(commentsChunks[counter])
}
}, [comments])
尝试将 youtube 评论加载到无限加载组件中(为此使用 npm)
由于无限加载组件是父 Accordion 组件的子组件(来自 react-bootstrap)以及我正在尝试的,所以发生了混乱仅当 Accordion 被点击(打开)时,achieve 才使用 useSWR 获取。
我尝试的是使用 useSWR 条件,以便仅在状态“show”为真时获取,这是在函数内部设置的:
const showComments = () => {
setShow(true)
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
}
调用了 Accordion.Toggle onClick 事件。
但是我点了两次手风琴之后才显示评论,这是为什么?
我的代码是:
import { useState, useEffect } from 'react'
import { Row, Col, Button, Accordion } from 'react-bootstrap'
import * as _ from 'lodash'
import useSWR from 'swr'
import { MdUnfoldMore } from 'react-icons/md'
import InfiniteScroll from "react-infinite-scroll-component"
import Comments from './Comments'
const siteurl = process.env.NEXT_PUBLIC_SITE_URL
export default function VideoComments({ video }){
const [show, setShow] = useState(false)
const [counter, setCounter] = useState(0)
const [commList, setCommList] = useState(null)
const [commChunks, setCommChunks] = useState([])
const showComments = () => {
setShow(true)
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
}
const fetcher = (...args) => fetch(...args).then(res => res.json())
const { data: comments, error } = useSWR(show ? `${siteurl}/api/c/${video.id}` : null, fetcher)
// useEffect(() => {
// if (comments) {
// commChunks = _.chunk(comments.comm, 10)
// setCommList(commChunks[counter])
// }
// },[comments])
const fetchMoreData = () => {
const newCounter = counter + 1;
// loaded all, return
if (commChunks[newCounter] === undefined || commChunks[newCounter] == null) {
return;
}
const newCommList = [
...commList,
...commChunks[newCounter]
]
setCommList(newCommList)
setCounter(newCounter)
}
return (
<div>
<Accordion>
<Row>
<Col xs={12}>
<Accordion.Toggle as={Button} onClick={() => {showComments()}} variant="link" eventKey="0"><div><span>Comments</span></div></Accordion.Toggle>
</Col>
</Row>
<Accordion.Collapse eventKey="0">
<div id="commentsBox" style={{maxHeight: '300px', overflowY: 'auto'}}>
<Col xs={12}>
{commList &&
<InfiniteScroll
dataLength={commList.length}
next={fetchMoreData}
hasMore={true}
scrollableTarget="commentsBox"
>
<Comments data={commList} />
</InfiniteScroll>
}
</Col>
</div>
</Accordion.Collapse>
</Accordion>
</div>
);
}
编辑:按照下面的建议,我重新激活了useEffect,但它仍然需要点击两次手风琴
const showComments = () => {
setShow(true)
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
}
const { data: comments } = useSWR(show ? `${siteurl}/api/c/${video.id}` : null, fetcher)
useEffect(() => {
if (comments) {
setCommChunks(_.chunk(comments.comm, 10))
setCommList(commChunks[counter])
}
},[comments])
您评论了处理评论的 useEffect
:
// useEffect(() => {
// if (comments) {
// commChunks = _.chunk(comments.comm, 10)
// setCommList(commChunks[counter])
// }
// },[comments])
发生了什么:
- 您点击手风琴,
showComments
被调用 show
设置为真,但是因为comments
未定义,所以commList
和commChunks
没有设置- 组件重新渲染,现在
useSWR
可以使用url获取数据 - 组件在获取 si 完成后重新呈现,现在
comments
包含数据 - 您第二次点击手风琴,
showComments
被调用 show
设置为true,这次设置commList
和commChunks
- 组件重新呈现
InfiniteScroll
和Comments
问题出在您的 useEffect
中,在修改 commChunks
状态后立即调用 setCommList(commChunks[counter])
不会有更新的值。在 React 中设置状态是一个异步操作(参见
您应该将注释保存在块范围变量中,并使用它来连续更新两种状态。
useEffect(() => {
if (comments) {
const commentsChunks = _.chunk(comments.comm, 10)
setCommChunks(commentsChunks)
setCommList(commentsChunks[counter])
}
}, [comments])