微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

useSWR 条件获取和 react-boostrap Accordion

如何解决useSWR 条件获取和 react-boostrap Accordion

尝试将 youtube 评论加载到无限加载组件中(使用 npm)

由于无限加载组件是父 Accordion 组件的子组件(来自 react-bootstrap),我试图实现的是仅在 Accordion 获取时使用 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 上,在修改 setCommList(commChunks[counter]) 状态后立即调用 commChunks 不会像您想象的那样工作。

您应该将注释保存在块范围变量中,并使用它来连续更新两个状态。

useEffect(() => {
    if (comments) {
        const commentsChunks = _.chunk(comments.comm,10)
        setCommChunks(commentsChunks)
        setCommList(commentsChunks[counter])
    }
},[comments])
,

您评论了处理评论的 useEffect :

  // useEffect(() => {
  //   if (comments) {
  //     commChunks = _.chunk(comments.comm,10)
  //     setCommList(commChunks[counter])
  //   }
  // },[comments])

发生了什么:

  1. 您单击手风琴,showComments 被调用
  2. show 设置为 true,但由于 comments 未定义,commListcommChunks 未设置
  3. 组件重新渲染,现在 useSWR 可以使用 url 获取数据
  4. 组件在获取 si 完成后重新渲染,现在 comments 包含数据
  5. 您第二次点击手风琴,showComments 被调用
  6. show 设置为 true,这次设置了 commListcommChunks
  7. 组件使用 InfiniteScrollComments 重新渲染

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?